Summerschool Aachen 2004/Fingerprinting Tool
#!/usr/bin/perl -w use strict; # --------------------------------------------------------------------------------- package Net::DNS::PacketExt; use strict; use vars qw(@ISA); @ISA = qw(Net::DNS::Packet); sub new { my $proto = shift; my $class = ref $proto || $proto; my $data = shift; my $self = Net::DNS::Packet->new($data); $self->{"header"} = Net::DNS::HeaderExt->new($data); bless $self, $class; return $self; } 1; # --------------------------------------------------------------------------------- package Net::DNS::HeaderExt; use strict; use vars qw(@ISA); @ISA = qw(Net::DNS::Header); sub new { my $proto = shift; my $class = ref $proto || $proto; my $data = shift; my $self = Net::DNS::Header->new($data); my @a = unpack("n C2 n4", $$data); $self->{"z0"} = ($a[2] >> 6) & 0x1; $self->{"z1"} = ($a[2] >> 5) & 0x1; $self->{"z2"} = ($a[2] >> 4) & 0x1; bless $self, $class; return $self; } 1; # --------------------------------------------------------------------------------- package MapTool; use strict; use Carp; sub new { my $proto = shift; my $class = ref $proto || $proto; my $targethost = $_[0] or croak "need target host"; my %self; $self{targethost} = $targethost; $self{smtp} = MapTool::Smtp->new(); $self{ftp} = MapTool::Ftp->new(); $self{dns} = MapTool::Dns->new(); bless \%self, $class; return \%self; } sub probe { my $self = shift; $self->{dns}->probe($self->{targethost}); } sub evaluate { my $self = shift; $self->{dns}->evaluate(); } sub printresults { my $self = shift; print $self->{dns}->printresults(); } 1; # --------------------------------------------------------------------------------- package MapTool::Smtp; use strict; use vars qw/@ISA/; use Carp; use Net::DNS::Resolver; @ISA = ("MapTool"); my $mydomain = 'ccc.de'; my $validsrc = 'cpunkt@ccc.de'; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $fpres = "smtp_fingerprints"; my $fpcmd = "smtp_tests"; my $self = {}; bless $self, $class; $self->mkdb($fpcmd, $fpres); return $self; } sub mkdb { my $self = shift; $self->{commands} = []; $self->{fingerprints} = {}; open TESTS, "$_[0]" or croak "can't open $_[0]"; open RESULTS, "$_[1]" or croak "can't open $_[1]"; while (my $tline = <TESTS>) { next if ($tline =~ /^#/); chomp $tline; my $invalidsrc = $self->generate_source_address(); $tline =~ s/\$MY_DOMAIN/${mydomain}/g; $tline =~ s/\$VALID_SOURCE/${validsrc}/g; $tline =~ s/\$INVALID_SOURCE/${invalidsrc}/g; my @cmd_sequence = split /->/, $tline; push @{$self->{commands}}, \@cmd_sequence; } close TESTS; while (my $rline = <RESULTS>) { next if ($rline =~ /^#/); chomp $rline; my @res_sequence = split /:/, $rline; my $software_version = shift @res_sequence; $self->{fingerprints}->{$software_version} = \@res_sequence; } close RESULTS; } sub generate_source_address { my ($i, $ok, $query); my ($fake_domain, $fake_user) = ('', ''); my $res = Net::DNS::Resolver->new; my @VALID_CHARS = ( 'A' .. 'Z', 'a' .. 'z', '0' .. '9', '_'); while (not $ok) { for $i (1 .. 25) { $fake_domain .= $VALID_CHARS[int rand(@VALID_CHARS)]; } $fake_domain .= '.com'; $ok = 1; $query = $res->query($fake_domain, 'SOA'); $ok = 1 if (not $query); } for $i (1 .. 10) { $fake_user .= $VALID_CHARS[int rand(@VALID_CHARS)]; } return "$fake_user\@$fake_domain"; } 1; # --------------------------------------------------------------------------------- package MapTool::Ftp; use strict; use vars qw/@ISA/; use Carp; @ISA = ("MapTool"); sub new { my $proto = shift; my $class = ref($proto) || $proto; my $fpres = "ftp_fingerprints"; my $fpcmd = "ftp_tests"; my $self = {}; bless $self, $class; $self->mkdb($fpcmd, $fpres); return $self; } sub mkdb { my $self = shift; $self->{commands} = []; $self->{fingerprints} = {}; open TESTS, "$_[0]" or croak "can't open $_[0]"; open RESULTS, "$_[1]" or croak "can't open $_[1]"; my $isnulled = 0; while (my $tline = <TESTS>) { next if ($tline =~ /^#/); chomp $tline; if ($tline =~ /^#if 0/) { $isnulled = 1; } elsif ($isnulled && $tline =~ /^#endif/) { $isnulled = 0; } next if ($isnulled || $tline !~ /^\s*"([^"]+)"/); push @{$self->{commands}}, $1; } close TESTS; my $inblock = 0; my $softwareversion; while (my $rline = <RESULTS>) { chomp $rline; if ($inblock && $rline =~ /^\s*\}/) { $inblock = 0; $softwareversion = ''; next; } elsif ($inblock) { my @checksums = split /,/, $rline; push @{$self->{fingerprints}->{$softwareversion}}, \@checksums; next; } if ($rline =~ /^\s*0UL,\s*"([^"]+)"/) { $softwareversion = $1; $inblock = 1 } } close RESULTS; } 1; # --------------------------------------------------------------------------------- package MapTool::Dns; use strict; use vars qw/@ISA/; use Carp; use Sys::Hostname; use Socket; @ISA = ("MapTool"); sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; bless $self, $class; $self->mkdb(); return $self; } sub mkdb { my $self = shift; $self->{commands} = []; $self->{fingerprints} = {}; $self->{commands} = [ "\0\0\10\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\0\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\3", "\0\0\0\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\77", "\0\0\0\0\0\2\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1\0\0\20\0\1", "\0\0\40\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\50\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\0\0\0\0\0\0\0\0\0\0", "\0\0\0\0\0\1\0\0\0\0\0\0\6", "\0\0\0\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0", "\0\0\2\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\0\0\0\1\0\0\0\0\0\0\7Authors\4BIND\0\0\20\0\3", "\0\0\4\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\0\17\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\0\20\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\0\40\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\0\100\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\20\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\30\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\60\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\0\0\0\1\0\0\0\0\0\0\4test\17network-surveys\2cr\2yp\2to\0\0\20\0\1", "\0\0\0\0\0\1\0\0\0\0\0\0\25erre-con-erre-cigarro\7maradns\3org\0\0\20\0\1", "\0\0\0\0\0\1\0\0\0\0\0\0\7version\6server\0\0\20\0\3", "\0\0\0\0\0\1\0\0\0\0\0\0\7version\4bind\0\0\20\0\3" ]; open FPR, "dns_fingerprints" || croak "couldn't open dns_fingerprints"; my $oldsep = $/; $/ = undef; my $fingerprints = <FPR>; $/ = $oldsep; close FPR; my $VAR1; eval $fingerprints; $self->{fingerprints} = $VAR1; } sub probe { my $self = shift; my $targethost = $_[0]; my $iaddr = inet_aton("0.0.0.0"); my $proto = getprotobyname('udp'); my $port = getservbyname('domain', 'udp'); my $paddr = sockaddr_in(0, $iaddr); socket(SOCK, PF_INET, SOCK_DGRAM, $proto) || croak "socket: $!"; bind(SOCK, $paddr) || croak "bind: $!"; $| = 1; my $hisiaddr = inet_aton($targethost) || croak "unknown host"; my $hispaddr = sockaddr_in($port, $hisiaddr); my $count = 0; foreach my $request (@{$self->{commands}}) { $count++; defined(send(SOCK, $request, 0, $hispaddr)) || croak "send ".$targethost.": $!"; my $rin = ''; vec($rin, fileno(SOCK), 1) = 1; my $rout; if (!select($rout = $rin, undef, undef, 5.0)) { $count > 2 && do { $count = 0; $self->pushresult("timeout"); next; }; redo; } my $response; ($hispaddr = recv(SOCK, $response, 1000, 0)) || croak "recv: $!"; $self->pushresult($response); $count = 0; } } sub pushresult { my $self = shift; my $result = $_[0]; push @{$self->{answers}}, $result; } sub evaluate { my $self = shift; if (scalar @{$self->{answers}} != scalar @{$self->{commands}}) { croak "number of answers doesn't match number of commands"; } $self->{results} = {}; $self->{results}->{probecount} = scalar @{$self->{answers}}; foreach my $swversion (keys %{$self->{fingerprints}}) { foreach my $y (@{$self->{fingerprints}->{$swversion}}) { my $matchcount; foreach my $i (0.. $#{$self->{answers}}) { $matchcount += $self->compare($self->{answers}->[$i], $y->[$i]); } push @{$self->{results}->{$matchcount}}, $swversion; } } $self->{results}->{signature} = $self->getsig; } my $cmpmatrix = [ ['Z0','Z1','Z2','Q2','0','1','2','3','4','5','TC','RD','AA','q','X','D'], ['$header->z0','$header->z1','$header->z2','$#queries == 1','$header->rcode eq "NOERROR"', '$header->rcode eq "FORMERR"','$header->rcode eq "SERVFAIL"','$header->rcode eq "NXDOMAIN"', '$header->rcode eq "NOTIMP"','$header->rcode eq "REFUSED"','$header->tc','$header->rd', '$header->aa','$#queries == -1','1','$#answers > -1'] ]; sub compare { my $self = shift; my ($response, $fingerprint) = @_; $fingerprint =~ s/\s+//g; if ($fingerprint =~ /t/) { return($response eq 'timeout'); } elsif ($response eq 'timeout') { return 0; } my @alternatives = split /,/, $fingerprint; my $packet = Net::DNS::PacketExt->new(\$response); $packet || croak("DNS::Packet refuses the response..."); my $header = $packet->header; my @queries = $packet->question; my @answers = $packet->answer; my $match = 0; foreach my $alternative (@alternatives) { foreach my $testcase (0.. $#{$cmpmatrix->[0]}) { my ($pattern, $value) = ($cmpmatrix->[0]->[$testcase], $cmpmatrix->[1]->[$testcase]); if ($alternative =~ s/${pattern}//) { $match = (eval $value); next unless $match; } } } return $match; } sub getsig { my $self = shift; my $fingerprint; foreach my $x (@{$self->{answers}}) { if ($x eq 'timeout') { $fingerprint .= 't --'; next; } my $packet = Net::DNS::PacketExt->new(\$x); $packet || croak("DNS::Packet refuses the response..."); my $header = $packet->header; my @queries = $packet->question; my @answers = $packet->answer; foreach my $testcase (0.. $#{$cmpmatrix->[1]}) { my ($condition, $output) = ($cmpmatrix->[1]->[$testcase], $cmpmatrix->[0]->[$testcase]); next if ($condition eq '1'); if (eval $condition) { $fingerprint .= "$output "; } } $fingerprint .= "-- "; } return $fingerprint; } sub printresults { my $self = shift; my $rv; for (my $score = $self->{results}->{probecount}; $score >= 0; $score--) { next unless (defined $self->{results}->{$score}); $rv .= "matched with score ".int ($score/(scalar @{$self->{answers}})*100).":\n"; my %uniq; map { next if $uniq{$_}; $uniq{$_}++; $rv .= "\t$_\n"; } @{$self->{results}->{$score}}; } $rv .= "\nserver signature:\n\t".$self->{results}->{signature}."\n"; return $rv; } 1; # --------------------------------------------------------------------------------- use strict; if ($#ARGV != 0) { print "usage: $0 <hostname>\n\n"; exit 1; } my $targethost = $ARGV[0]; my $map = MapTool->new($targethost); $map->probe(); $map->evaluate(); $map->printresults();
This is the file "dns_fingerprints", I have built from djb's HTML page. I've also added some new signatures...
$VAR1 = { 'tinydns 1.04 with local root' => [ [ '4AA','t','t','t','4AA','4AA','t','t','t','4AA','t','4AA','0AA','0AA','0AA','0AA','4AA','4AA','4AA','0AA','0AA','t','t' ] ], 'tinydns 1.05 with local root' => [ [ '4AA','1RD','1RD','t','4AA','4AA','t','t','t','4AA','1RD','4AA','0AA','0AA','0AA','0AA','4AA','4AA','4AA','0AA','0AA','1RD','1RD' ] ], 'tinydns 1.05 with wildcard root' => [ [ '4AA','1RD','1RD','t','4AA','4AA','t','t','t','4AA','1RD','4AA','3AA','3AA','3AA','3AA','4AA','4AA','4AA','3AA','3AA','1RD','1RD' ] ], 'tinydns 1.05 variant' => [ [ '4AA','1RD','1RD','t','4AA','4AA','t','t','t','4AA','1RD','4AA','5','5','5','5','4AA','4AA','4AA','5','5','1RD','1RD' ] ], 'tinydns 1.04 with wildcard root' => [ [ '4AA','t','t','t','4AA','4AA','t','t','t','4AA','t','4AA','3AA','3AA','3AA','3AA','4AA','4AA','4AA','3AA','3AA','t','t' ] ], 'tinydns 1.05' => [ [ '4AA','1RD','1RD','t','4AA','4AA','t','t','t','4AA','1RD','4AA','t','t','t','t','4AA','4AA','4AA','t','t','1RD','1RD' ] ], 'tinydns 1.05 with big root' => [ [ '4AA','1RD','1RD','t','4AA','4AA','t','t','t','4AA','1RD','4AA','0TC','0TC','0TC','0TC','4AA','4AA','4AA','0TC','0TC','1RD','1RD' ] ], 'tinydns 1.04' => [ [ '4AA','t','t','t','4AA','4AA','t','t','t','4AA','t','4AA','t','t','t','t','4AA','4AA','4AA','t','t','t','t' ] ], 'tinydns 1.04 with root NS' => [ [ '4AA','t','t','t','4AA','4AA','t','t','t','4AA','t','4AA','0','0','0','0','4AA','4AA','4AA','0','0','t','t' ] ], 'tinydns 1.05 with root NS' => [ [ '4AA','1RD','1RD','t','4AA','4AA','t','t','t','4AA','1RD','4AA','0','0','0','0','4AA','4AA','4AA','0','0,0TC','1RD','1RD' ] ], 'BIND 4.9.8-' => [ [ '1q','0,2','0,2','1q','4q,5,2','4q','1q','1q','1q','0TC','0,2','0,2','0,2','0Z0,2Z0','0Z1,2Z1','0Z2,2Z2','4q','4q','4q','0,2','0,2','0,2','0,2,0AAD' ] ], 'BIND 9.1' => [ [ '4q','5','5','1q','5','1q','1q','1q','1q','0','0AA','0','15','0','0','0','4q','4q','4q','0','0','5','0AAD,2,5' ], [ '4q','5','5','1q','5','1q','1q','1q','1q','2','0AA','2','2','2','2','2','4q','4q','4q','2','2','5','0AAD,2,5' ], [ '4q','5','5','1q','5','1q','1q','1q','1q','5','0AA','5','5','5','5','5','4q','4q','4q','5','5','5','0AAD,2,5' ] ], 'BIND 9.2' => [ [ '4q','5','5','1q','2','1q','1q','1q','1q','0AA','0AA,5','0AA','0AA','0AA','0AA','0AA','4q','4q','4q','0AA','0AA','5','0AAD,2,5' ], [ '4q','5','5','1q','2','1q','1q','1q','1q','3AA','0AA','3AA','3AA','3AA','3AA','3AA','4q','4q','4q','3AA','3AA','5','0AAD,2,5' ], [ '4q','5','5','1q','2','1q','1q','1q','1q','0,2,3,5','0AA,2,5','0,2,3,5','0,5,15','0,2,3,5','0,2,3,5','0,2,3,5','4q','4q','4q','0,2,3,5','0,2,3AA,5','5','0AAD,2,5' ] ], 'BIND 8.2-' => [ [ '1q','0,2,5','0,2,5','1q','2,4,5','1q','1q','1q','1q','0TC,0TCZ1,3TC,5TC','0,0AA,2,3,3AA,5','0,2,3,3AA,5','0,2,3,3AA,5','0Z0,2Z0,3AAZ0,3Z0,5Z0','0Z1,2Z1,3AAZ1,3Z1,5Z1', '0Z2,2Z2,3AAZ2,3Z2,5Z2','4q','4q','4q','0,2,3,3AA,5','0,0AA,2,3,3AA,5','0,2,3,5','0AAD,0,3,5' ], [ '1q','0,2,5','0,2,5','1q','2,4,5','1q','1q','1q','1q','0TC,0TCZ1,3TC,5TC','0,0AA,2,3,3AA,5','0,0AA,2,3,3AA,5','0,0AA,2,3,3AA,5','0Z0,0AAZ0,2Z0,3AAZ0,3Z0,5Z0','0,0AA,2,3,3AA', '0Z2,0AAZ2,2Z2,3AAZ2,3Z2,5Z2','4q','4q','4q','0,0AA,2,3,3AA,5','0,0AA,2,3,3AA,5','0,2,3,5','0AAD,0,3,5' ] ], 'BIND 9.3' => [ [ '4q','2','5','1q','2,5','1q','1q','1q','1q','0,5','0AA,2,3AA,5','0','0','0','0','0','4q','4q','4q','0','0','2,5','0AAD,2,3AA,5' ], [ '4q','2','5','1q','2,5','1q','1q','1q','1q','0,5','0AA,2,3AA,5','0','15','0','0','0','4q','4q','4q','0','0','2','0AAD,2,3AA,5' ], [ '4q','2','5','1q','2,5','1q','1q','1q','1q','0,5','0AA,2,3AA,5','5','5','5','5','5','4q','4q','4q','5','5','2','0AAD,2,3AA,5' ] ], 'BIND 4.9.7' => [ [ '1q','0,2','0,2','1q','4q,5,2','4q','1q','1X','1','0TC,2TC','0,2','0,2,0AA,2AA','0,2,0AA','0AAZ0','0AAZ1','0AAZ2','4q','4q','4q,5q','0AA','0AA','0,2','0,2,0AAD' ], [ '1q','0,2','0,2','1q','4q,5,2','4q','1q','1X','1','0TC,2TC','0,2','0,2,0AA,2AA','0,2,0AA','0Z0,2Z0','0Z1,2Z1','0Z2,2Z2','4q','4q','4q,5q','0,2','0,2','0,2','0,2,0AAD' ] ], 'BIND 8.1' => [ [ '1q','0,2,5','0,2,5','1q','2,4,5','1q','1q','1X','1','0TC,0TCZ1,3TC,5TC','0,0AA,2,3,3AA,5','0,2,3,3AA,5','0,2,3,3AA,5','0Z0,2Z0,3AAZ0,3Z0,5Z0','0Z1,2Z1,3AAZ1,3Z1,5Z1','0Z2,2Z2,3AAZ2,3Z2,5Z2', '4q','4q','4q','0,2,3,3AA,5','0,0AA,2,3,3AA,5','0,2,3,5','0AAD,0,3,5' ], [ '1q','0,2,5','0,2,5','1q','2,4,5','1q','1q','1X','1','0TC,0TCZ1,3TC,5TC','0,0AA,2,3,3AA,5','0,2,3,3AA,5','0,2,3,3AA,5','0Z0,2Z0,3AAZ0,3Z0,5Z0','0','0Z2,2Z2,3AAZ2,3Z2,5Z2','4q','4q','4q', '0,2,3,3AA,5','0,0AA,2,3,3AA,5','0,2,3,5','0AAD,0,3,5' ], [ '1q','0,2,5','0,2,5','1q','2,4,5','1q','1q','1X','1q','0TC,0TCZ1,3TC,5TC','0,0AA,2,3,3AA,5','0,2,3,3AA,5','0,2,3,3AA,5','0Z0,2Z0,3AAZ0,3Z0,5Z0','0Z1,2Z1,3AAZ1,3Z1,5Z1','0Z2,2Z2,3AAZ2,3Z2,5Z2', '4q','4q','4q','0,2,3,3AA,5','0,0AA,2,3,3AA,5','0,2,3,5','0AAD,0,3,5' ] ], 'BIND 9.0' => [ [ '4q','5','5','1q','5','1q','5q','1q','1q','0Z1','5','0Z1','15Z1','0Z1','0Z1','0Z1','4q','4q','4q','0Z1','0Z1','5','0AAZ1D,2,5' ] ], 'BIND 8.3.4' => [ ['1q','2','2','1q','2','1q','1q','1q','1q','0TC','2','0','0','0Z2','0','0Z0','4q','4q','4q','0','0','2','0AAD' ] ], 'POWERDNS' => [ [ '4AA','0AA','0AAX','2X,0AAX','0AAX,2AA','0AAX,4AA','0AA,t','t','0AA,2,t','0AAX,2','0AA','0AAX,2','0AAX','0AAX','0AAX','0AAX','0AAX','0AAX','0AAX','0AAX','0AA,2','0AA','0AAD' ], [ '4AA','0AA','0AAX','2X,0AAX','0AAX,2AA','0AAX,4AA','0AA,t','t','0AA,2,t','0AAX,2','0AA','0AAX,2','0AAX','0AAX','0AAX','2','2','2','2','2','2','0AA','0AAD' ], [ '4AA','0AA','0AAX','2X,0AAX','0AAX,2AA','0AAX,4AA','0AA,t','t','0AA,2,t','0AAX,2','0AA','0AAX,2','2','2','2','2','2','2','0AAX,2','0AAX,2','2','0AA','0AAD' ], [ '4AA','0AA','0AA','2X','4AA','4AA','0AA','t','0AA','2','0AA','2','2','2','2','2','4AA','4AA','4AA','2','2','0AA','0AAD' ], [ '4AA','0AA','0AAX','3AAX','0AAX','0AAX','0AA','t','3AA','3AA','0AA','3AA','3AA','3AA','3AA','3AA','3AA','3AA','3AA','3AA','3AA','0AA','0AAD' ] ], 'eNom DNS server' => [ [ '0','0X','0X','0Q2','0','0','1q','t','t','0','0X','0','0','0','0','0','0','0','0','0','0','0X','0X' ] ], 'NSD' => [ [ '4q','5','5','1q','4q','4q','1q','1q','1q','1q','5','2','2','2','2','2','4q','4q','4q','2','2','0D','5' ] ], 'MaraDNS 1.0-' => [ [ '4q','5q','5q','t','4q','4q','4q','t','t','5q','5q','5q','5q','5q','5q','5q','4q','4q','4q','5q','0D,5q','5q','5q' ] ], 'Incognito DNS Commander 3.5-' => [ [ '4X','0,2,5','1','0,0AA,0AAQ2,0Q2,3AAQ2,3Q2X','3','1,5','1','1X','1','0','0AA,2','0','15','0','0','0','4X','4X','4X','0','0,0AA','2,5','0AAD' ] ], 'Incognito DNS Commander -3.2' => [ [ '4X','0,2,5','1','0,0AA,0AAQ2,0Q2,3AAQ2,3Q2X','0,3','0X,1,5','0q','1,2X','1','0','0','0','15','0','0','0','4X','4X','4X','0','0','0','0AAD' ] ], 'UltraDNS' => [ [ '4','0','0','1q','3','9','1q','1q','0','0','0','0','0','0','0','0','4','4','4','0','0','0','0AAD' ] ], 'Simple DNS Plus' => [ [ '4','4','4','0X','4','1','t','1','1','0','4','0','0','0','0','0','4','4','4','0','0','4','0D,4' ], [ '4','4','4','0AAX','4','1','t','1','1','0AA','4','0AA','0AA','0AA','0AA','0AA','4','4','4','0AA','0AA','4','0D,4' ], [ '4','4','4','0X','t','4','t','t','t','0','4','0','0','0','0','0','4','4','4','0','0','4','0D,4' ] ], 'MaraDNS before 1.0' => [ [ '4q','5q','5q','4q','4q','4q','4q','t','t','5q','5q','5q','5q','5q','5q','5q','4q','4q','4q','5q','0D','5q','5q' ] ] };
--Cpunkt 18:16, 30 Sep 2004 (CEST)