#!/usr/bin/perl -w # A quick decoder for captured network data, for the Reverse Challenge. # Requires tcpdump to be in the current path. # # Dion Mendel 27th May 2002 use strict; if (scalar @ARGV != 1) { print "Usage: $0 \n"; print "Decodes a tcpdump style capture file for the Reverse Challenge\n"; exit 1; } my $filename = $ARGV[0]; my @packets = &get_packets($filename); my ($pdu, $val, $last, $handler_to_agent, @decoded); foreach $pdu (@packets) { # ensure these packets use the protocol next unless (($pdu->[20] == 2) or ($pdu->[20] == 3)); # print IP addresses and direction printf "%d.%d.%d.%d -> %d.%d.%d.%d ", $pdu->[12], $pdu->[13], $pdu->[14], $pdu->[15], $pdu->[16], $pdu->[17], $pdu->[18], $pdu->[19]; $handler_to_agent = $pdu->[20] == 2; printf "(%s)\n", $handler_to_agent ? "handler -> agent" : "agent -> handler"; # decode data $last = scalar(@$pdu) - 1; @decoded = &decode(@$pdu[22..$last]); # dump packet &dump($handler_to_agent, @decoded); print "----------------------------------------------------------------\n"; } exit (0); # Dumps the details of decoded packets. sub dump($@) { my ($to_agent, @data) = @_; my ($cmd, $port, $str); $cmd = $data[1]; if ($to_agent) { if ($cmd == 1) { printf "Request for status report.\n"; } elsif ($cmd == 2) { printf "Initialise agent.\n", $data[2]; if ($data[2] == 0) { printf("All replies are sent to handler at %d.%d.%d.%d\n", $data[3], $data[4], $data[4], $data[6]); } elsif ($data[2] == 2) { printf("All replies are to be sent to handlers at:\n" . "%d.%d.%d.%d\n" . "%d.%d.%d.%d\n" . "%d.%d.%d.%d\n" . "%d.%d.%d.%d\n" . "%d.%d.%d.%d\n" . "%d.%d.%d.%d\n" . "%d.%d.%d.%d\n" . "%d.%d.%d.%d\n" . "%d.%d.%d.%d\n" . "%d.%d.%d.%d\n", $data[3], $data[4], $data[5], $data[6], $data[7], $data[8], $data[9], $data[10], $data[11], $data[12], $data[13], $data[14], $data[15], $data[16], $data[17], $data[18], $data[19], $data[20], $data[21], $data[22], $data[23], $data[24], $data[25], $data[26], $data[27], $data[28], $data[29], $data[30], $data[31], $data[32], $data[33], $data[34], $data[35], $data[36], $data[37], $data[38], $data[39], $data[40], $data[41], $data[42]); } else { printf("All replies are sent to handler at %d.%d.%d.%d\n" . "(plus 9 other randomly generated hosts)\n", $data[3], $data[4], $data[4], $data[6]); } } elsif ($cmd == 3) { $str = pack("C*", @data[2..$#data]); $str = substr($str, 0, index($str, "\0")); printf("Execute the given command and send output to handler:\n%s\n", $str); } elsif ($cmd == 4) { $port = ($data[6] << 8) + $data[7]; if ($data[8] != 0) { $str = pack("C*", @data[9..$#data]); $str = substr($str, 0, index($str, "\0")); printf("Perform custom DNS flood on victim %s,\n" . "using spoofed source port %d\n", $str, $port); } else { printf("Perform custom DNS flood on victim %d.%d.%d.%d,\n" . "using spoofed source port %d\n", $data[2], $data[3], $data[4], $data[5], $port); } } elsif ($cmd == 5) { $port = ($data[6] << 8) + $data[7]; if ($data[12] != 0) { $str = pack("C*", @data[13..$#data]); $str = substr($str, 0, index($str, "\0")); printf("Perform jolt2 attack on victim %s,\n", $str); } else { printf("Perform jolt2 attack on victim %d.%d.%d.%d,\n", $data[4], $data[5], $data[6], $data[7]); } if ($data[2] != 0) { printf("using udp port %d,\n", $data[3]); } else { printf("using icmp,\n"); } printf("and spoofed source IP of %d.%d.%d.%d\n", $data[8], $data[9], $data[10], $data[11]); } elsif ($cmd == 6) { printf("open a backdoor root shell\n" . "(default port is 23281 and default password is SeNiF)\n"); } elsif ($cmd == 7) { $str = pack("C*", @data[2..$#data]); $str = substr($str, 0, index($str, "\0")); printf("Execute the given command, " . "do not send output to handler:\n%s\n", $str); } elsif ($cmd == 8) { printf("Terminate current action (if any)\n"); } elsif ($cmd == 9) { $port = ($data[7] << 8) + $data[8]; if ($data[9] != 0) { $str = pack("C*", @data[10..$#data]); $str = substr($str, 0, index($str, "\0")); printf("Perform custom DNS flood on victim %s,\n" . "using spoofed source port %d and parameter %d\n", $str, $port, $data[6]); } else { printf("Perform custom DNS flood on victim %d.%d.%d.%d,\n" . "using spoofed source port %d and parameter %d\n", $data[2], $data[3], $data[4], $data[5], $port, $data[6]); } } elsif ($cmd == 10) { $port = ($data[6] << 8) + $data[7]; if ($data[13] != 0) { $str = pack("C*", @data[14..$#data]); $str = substr($str, 0, index($str, "\0")); printf("Perform synflood on victim %s\n", $str); } else { printf("Perform synflood on victim %d.%d.%d.%d\n", $data[2], $data[3], $data[4], $data[5]); } printf("using port %d,\n", $port); if ($data[8] != 0) { printf("using spoofed source IP address %d.%d.%d.%d\n", $data[9], $data[10], $data[11], $data[12]); } else { printf("using random spoofed source IP addresses\n"); } } elsif ($cmd == 11) { $port = ($data[6] << 8) + $data[7]; if ($data[14] != 0) { $str = pack("C*", @data[15..$#data]); $str = substr($str, 0, index($str, "\0")); printf("Perform synflood on victim %s\n", $str); } else { printf("Perform synflood on victim %d.%d.%d.%d\n", $data[2], $data[3], $data[4], $data[5]); } printf("using port %d and parameter %d\n", $port, $data[13]); if ($data[8] != 0) { printf("using spoofed source IP address %d.%d.%d.%d\n", $data[9], $data[10], $data[11], $data[12]); } else { printf("using random spoofed source IP addresses\n"); } } elsif ($cmd == 12) { $port = ($data[11] << 8) + $data[12]; if ($data[13] != 0) { $str = pack("C*", @data[14..$#data]); $str = substr($str, 0, index($str, "\0")); printf("Perform custom DNS flood (using dns server %s)\n", $str); } else { printf("Perform custom DNS flood (using dns server %d.%d.%d.%d)\n", $data[2], $data[3], $data[4], $data[5]); } printf("on victim %d.%d.%d.%d\n" . "using spoofed source port %d,\n" . "and parameter %d\n", $data[6], $data[7], $data[8], $data[9], $port, $data[10]); } } else { if ($cmd == 1) { if ($data[3] == 1) { printf "agent is currently executing task: %s\n", &task_name($data[4]); } else { printf "agent is not executing any task\n"; } } elsif ($cmd == 3) { printf "output of command executed by agent:\n"; $str = pack("C*", @data[2..$#data]); $str = substr($str, 0, index($str, "\0")); printf "%s\n", $str; } elsif ($cmd == 4) { $str = pack("C*", @data[2..$#data]); $str = substr($str, 0, index($str, "\0")); if (length($str) == 1) { printf "continuing output of command executed by agent:%s\n"; } else { printf "end of output of command executed by agent\n"; } } } } # Returns human readable string of possible tasks. sub task_name($) { my ($number) = @_; return "no task" if $number == 0; return "custom dns flood" if $number == 4; return "jolt 2 attack" if $number == 5; return "providing backdoor" if $number == 6; return "custom dns flood" if $number == 9; return "syn flood" if $number == 10; return "syn flood" if $number == 11; return "custom dns flood (with specified DNS server)" if $number == 12; return "unknown"; } # Function to decode a given array. sub decode(@) { my (@src) = @_; my ($i, $val, @dst); @dst = (); for ($i = $#src; $i >= 1; $i--) { $val = $src[$i] - ($src[$i - 1] + 23); while ($val < 0) { $val += 256; } $dst[$i] = $val; } $val = $src[0] - 23; while ($val < 0) { $val += 256; } $dst[0] = $val; return @dst; } # Returns list of packets from a tcpdump file. Packets are returned as # an array of integers. sub get_packets($) { my (@filename) = @_; my (@output, @text_packets, @packets, @tmp, $line, $packet, $grab); @output = `tcpdump -n -x -r $filename`; @text_packets = (); $packet = ""; $grab = 0; foreach $line (@output) { chomp($line); if ($line =~ /^\S/) { if ($line =~ /ip-proto-11/) { $grab = 1; if ($packet ne "") { push @text_packets, $packet; $packet = ""; } } else { $grab = 0; } } elsif ($grab) { $packet .= $line; } } if ($packet ne "") { push @text_packets, $packet; $packet = ""; } # *sigh* there must be a better way to do this @packets = (); foreach $packet (@text_packets) { $packet =~ s/\s//g; @tmp = unpack "a2" x (length($packet) / 2), $packet; my @pdu = map { oct('0x' . $_) } @tmp; push @packets, \@pdu; } return @packets; }