#!/usr/bin/perl -w

##
# Author: Benjamin Kuperman
# Date: 28 May 2002
#
# Decodes data packets as part of the Honeynet Reverse Engineering
# Challenge
##

my $inpacket=0;

while (<>) {
    if (m!(\d{2}/\d{2}-\d{2}:\d{2}:\d{2}.\d{6}) (\d+.\d+.\d+.\d+) -> (\d+.\d+.\d+.\d+)!) {
	my @packet=();
	$stamp=$1;
	$src_ip=$2;
	$dest_ip=$3;
	# Now get the next line
	$line = <>;
	if (($proto,$ttl,$tos,$id,$iplen,$dgmlen) 
		= ($line =~ /PROTO(\d+) TTL:(\d+) TOS:(\S+) ID:(\d+) IpLen:(\d+) DgmLen:(\d+)/)) {
	    # process this record
	    print "$src_ip -> $dest_ip: Length $dgmlen\n";
	    $seen = 0;
	    while (1) {
		$line = <>;
		chomp($line);
		last unless  ($line =~ s/^(.*?)  .*/$1/);
		foreach $byte (split " ",$line) {
		    # process each byte
		    $val=eval "0x$byte";
		    $packet[$seen] = $val;
		    $seen++;
		}
	    }
	    # I should have a full packet
	    #print "Packet has ". @packet . " bytes\n";
	    ## Decode
	    # Skip first two bytes
	    $p1 = shift @packet;
	    $p2 = shift @packet;
	    # leave the first byte alone
	    for ($i=@packet-1;$i>0; $i--) {
		# but subtract prev from all subsequent bytes
		$packet[$i] -= $packet[$i-1];
		# subtract 23
		$packet[$i] -= 23;
		# make sure it is positive
		while ($packet[$i] < 0) { $packet[$i] += 256 };
		warn "Unexpected value in position $i of $packet[$i]\n" if ($packet[$i]>255);
		
	    }
	    #print "First two bytes were $p1 $p2\n";
	    if ("$p2 $p1" eq "0 2") {
		$command=$packet[1] - 1;
		print "Command was case $command -- ";
		if ($command == 0) {
		    print "Status Request.\n";
		} elsif ($command == 1) {
		    print "Configuration.\n";
		    $globalvar007 = $packet[0]; # used later
			if ($globalvar007 == 2) {
			    for ($i=0;$i<10;$i++) {
				printf("\t IP address #%d: %d.%d.%d.%d\n",$i,
					$packet[3+($i*5)],
					$packet[4+($i*4)],
					$packet[5+($i*4)],
					$packet[6+($i*4)]);
			    }
			} else {
			    print "\t Using random target addresses\n";
			}
		    printf("\t IP address for skip: %d.%d.%d.%d\n",  $packet[3],
			    $packet[4],
			    $packet[5],
			    $packet[6]);
		    $lastskip=$packet[3] .".".$packet[4].".".$packet[5].".".$packet[6];
		} elsif ($command == 2) {
		    print "Execute command.\n";
		    print "requested command was \'";
		    for ($i=2;$i<@packet;$i++) {
			$val=$packet[$i];
			last if ($val == 0 );
			printf ("%c",$val);
		    }
		    print "\'\n";
		} elsif ($command == 3) {
		    print "DoS: DNS-UDP\n";
#    dos_dns_udp(buffer2[2], buffer2[3], buffer2[4], buffer2[5], 0, 
#	     buffer2[6], buffer2[7], buffer2[8], buffer5);
### Expand here
		    print "\t         Source Addr: ".$packet[2].".".$packet[3].".".$packet[4].".".$packet[5]."\n";
		    print "\tUDP      Source Port: ".$packet[6]."\n";
		    print "\tUDP Destination Port: ".$packet[7]."\n";
		    print "\tpossible source addr: ";
		    ## The following might need to start with 11
		    for ($i=9;$i<@packet;$i++) {
			$val=$packet[$i];
			last if ($val == 0 );
			printf ("%c",$val);
		    }
		    print "\n";
		} elsif ($command == 4) {
#    send_udp_or_icmp( buffer2[2], buffer2[3], buffer2[4], buffer2[5], 
#		      buffer2[6], buffer2[7], buffer2[8], buffer2[9], 
#		      buffer2[10], buffer2[11], buffer2[12], buffer5);
		    print "DoS: UDP or ICMP\n";
		    print "\t Type will be ";
		    if ($packet[2] > 0) {
			print "UDP\n";
		    } else {
			print "ICMP\n";
		    }
		    print "\tUDP Destination Port: ".$packet[3]."\n";
		    print "\t    Destination Addr: ".$packet[4].".".$packet[5].".".$packet[6].".".$packet[7]."\n";
		    print "\t         Source Addr: ".$packet[8].".".$packet[9].".".$packet[10].".".$packet[11]."\n";
		    if ($packet[12] == 0) {
			print "\t Will use destination address\n";
		    } else {
			print "\t Will not use destination address\n";
			print "\t possible destination addr: ";
			## The following might need to start with 15
			for ($i=13;$i<@packet;$i++) {
			    $val=$packet[$i];
			    last if ($val == 0 );
			    printf ("%c",$val);
			}
			print "\n";
		    }
		} elsif ($command == 5) {
		    print "open root shell on port 23281\n";
		} elsif ($command == 6) {
		    print "Execute command - with parent alive for 20 mins - no response\n";
		    print "requested command was \'";
		    for ($i=2;$i<@packet;$i++) {
			$val=$packet[$i];
			last if ($val == 0 );
			printf ("%c",$val);
		    }
		    print "\'\n";

		} elsif ($command == 7) {
		    print "Kill active process\n";
		} elsif ($command == 8) {
#    dos_dns_udp( buffer2[2], buffer2[3], buffer2[4], buffer2[5], buffer2[6], 
#	      buffer2[7], buffer2[8], buffer2[9], buffer5);
		    print "DoS: DNS-UDP (flood)\n";
			print "\t         Source Addr: ".$packet[2].".".$packet[3].".".$packet[4].".".$packet[5]."\n";
			$val = (256 * $packet[7]) + $packet[8];
			print "\t    UDP  Source Port: ".$val."\n";
			print "\t Will delay every ".$packet[6]." packets\n";
			print "\t possible destination addr: ";
			## The following might need to start with 12
			for ($i=10;$i<@packet;$i++) {
			    $val=$packet[$i];
			    last if ($val == 0 );
			    printf ("%c",$val);
			}
			print "\n";
		} elsif ($command == 9) {
		    print "DoS: TCP Synflood";
#    send_tcp( buffer2[2], buffer2[3], buffer2[4], buffer2[5], buffer2[6], 
#	      buffer2[7], buffer2[8], buffer2[9], buffer2[10], buffer2[11], 
#	      buffer2[12], 0, buffer2[13], buffer5);
		    print "\tDestination Addr: ".$packet[2].".".$packet[3].".".$packet[4].".".$packet[5]."\n";
		    $val = (256 * $packet[6]) + $packet[7];
		    print "\t   TCP Dest Port: ".$val."\n";
		    if ($packet[8] == 0) {
			print "\t Using random source address\n";
		    } else {
			print "\t      Source Addr: ".$packet[9].".".$packet[10].".".$packet[11].".".$packet[12]."\n";
		    }
		    if ($packet[13] == 0) {
			print "\t Will use destination address\n";
		    } else {
			print "\t Will not use destination address\n";
			print "\t possible destination addr: ";
			## The following might need to start with 16
			for ($i=14;$i<@packet;$i++) {
			    $val=$packet[$i];
			    last if ($val == 0 );
			    printf ("%c",$val);
			}
			print "\n";
		    }
		} elsif ($command == 10) {
		    print "DoS: TCP Synflood (flood)";
		    print "\tDestination Addr: ".$packet[2].".".$packet[3].".".$packet[4].".".$packet[5]."\n";
		    $val = (256 * $packet[6]) + $packet[7];
		    print "\t   TCP Dest Port: ".$val."\n";
		    if ($packet[8] == 0) {
			print "\t Using random source address\n";
		    } else {
			print "\t      Source Addr: ".$packet[9].".".$packet[10].".".$packet[11].".".$packet[12]."\n";
		    }
			print "\t Will delay every ".$packet[13]." packets\n";
		    if ($packet[14] == 0) {
			print "\t Will use destination address\n";
		    } else {
			print "\t Will not use destination address\n";
			print "\t possible destination addr: ";
			## The following might need to start with 17
			for ($i=15;$i<@packet;$i++) {
			    $val=$packet[$i];
			    last if ($val == 0 );
			    printf ("%c",$val);
			}
			print "\n";
		    }
		} elsif ($command == 11) {
		    print "DoS: DNS reflector\n";
		} else {
		    print "Unexpected command #$command -- dumping packet\n";
		    for ($i=0;$i<@packet;$i++) {
			$val = $packet[$i];
			#print "." if ($val < 20);
			#printf("%c",$val) if ($val>=20);
			printf("%02X ",$val);
			print "\n" if !(($i+1) % 16);
		    }
		}
		print "\n";
		next;
	    } elsif ("$p2 $p1" eq "0 3") {
		print "Zombie reply: ";
		if ($lastskip eq $dest_ip) {
		    print "** actual destination **\n"
		} else {
		    print "fake destination\n"
		}
		for ($i=2;$i<@packet;$i++) {
		    $val=$packet[$i];
		    last if ($val == 0 );
		    printf ("%c",$val);
		}
		print "\n";
	    } else {
	    }
	} else {
	    chomp($line);
	    print "ERROR: unexpected line \"$line\"\n";
	    next;
	}
    } else {
	next;
    }
}

exit 0;

$val = "$stamp $ttl $id $proto $tos $iplen";

