#!/usr/bin/perl

use Net::DNS;

sub get_axfr{
print "\nInitiating Zone Transfer ...\n";
$res->usevc(1);
@zone = $res->axfr($domain);
   if (@zone) {
       foreach $rr (@zone) {
           $rr->print;
       }
       print "\n----------------------------------------------------------------------\n\n";
       return 1;
   }
   else {
       print ';;Zone transfer failed: ', $res->errorstring, "\n";
       print "\n----------------------------------------------------------------------\n\n";
       return 0;
   }
}

sub find_rootserver{
$res->usevc(0);
if (open(ROOT,"root-servers.dat")){
 while (<ROOT>){
        chomp($_);
        $res->nameservers($_);
        print "Asking Root Server $_\n";
        $packet=$res->send($domain, 'NS');
        if ($packet){
        @additional_tld = $packet->additional;
        if (@additional_tld) {
            foreach $rr (@additional_tld) {
            $tld=$rr->rdatastr;
            if (find_ns()){close(ROOT); return 1;}
            else {print "No Records found!\n";}
            }
            }
            }
        }
        close(ROOT);            
        return 0;
        die "Can't connect to the Root-Servers! \n";
    }
  else {die "Can't open root-servers.dat!\n";}
close(ROOT);
}

sub resolve_name{
# Enter the IP of your favorite DNS Server in the next line
#$res->nameservers('217.5.115.7');
if (open(DNS,"dns-server.dat")){
 while (<DNS>){
        chomp($_);
        $res->nameservers($_);
        }
   }
close(DNS);
print "Resolving $name\n";
$packet_resolve=$res->send($name,'ANY');
if ($packet_resolve){
    @nameserv = $packet_resolve->answer;
    if (@nameserv) {
        foreach $rr (@nameserv) {
        $ns=$rr->rdatastr;}
    }
   }
}

sub find_ns{
$ok=0;
$res->usevc(0);
$res->recurse(1);
$res->nameservers($tld);
print "Asking TLD Server $tld\n";
$packet=$res->send($domain, 'NS');
if ($packet){
    @additional_ns = $packet->additional;
    @answer_ns = $packet->answer;
    if (@additional_ns) {
        foreach $rr (@additional_ns) {
        $ns=$rr->rdatastr;
        if (get_dns()){$ok= 1;}
        }
        if ($ok){return 1;}
    }
    else {
    if (@answer_ns) {
        foreach $rr (@answer_ns) {
        $name=$rr->rdatastr;
        resolve_name();
        if (get_dns()){$ok= 1;}
        }
        if ($ok){return 1;}
    }
    else {return 0;}
    }
}
return 0;
}

sub get_dns(){
$res->nameservers($ns);
$res->usevc(0);
print "Asking Name Server $ns\n";
if ($version){get_ver();}
$packet=$res->send($domain, 'NS');
if ($packet){
if ( get_axfr()){
   print " Zone Transfer succesful!\n";
   }
else {
    get_any();
    get_activedir();
    if ($dig){dig_dns();}
    print "All possible information for $domain gathered!\n";
}
return 1;
}
else {return 0;}
}

sub get_ver{
$res->usevc(0);
print "\nChecking for DNS Server Version ...\n";
$packet=$res->query('version.bind', 'TXT','CH');
if ($res->errorstring eq "NOTIMP"){print "Microsoft DNS Server detected!\n";}
if ($res->errorstring eq "FORMERR"){print "TinyDNS Server detected!\n";}
if ($res->errorstring eq "NOERROR")
{
   print "BIND DNS Server detected!\n";
   if ($packet) {
    @dnsversion = $packet->answer;
    if (@dnsversion) {
        foreach $rr (@dnsversion) {
        $ver=$rr->rdatastr;
        print "BIND Version: $ver \n";}
    }
   }
}
}

sub get_any{
print "\nGetting ANY DNS Record ...\n";
$res->usevc(0);
$packet=$res->query($domain, 'ANY');
if ($packet) {
    $packet->print;
    print "\n----------------------------------------------------------------------\n\n";
   }
@dnstypes=(
"A",
"AAAA",
"AFSDB",
"CERT",
"CNAME",
"DNAME",
"EID",
"HINFO",
"ISDN",
"LOC",
"MB",
"MG",
"MINFO",
"MR",
"MX",
"NAPTR",
"NIMLOC",
"NS",
"NSAP",
"NULL",
"OPT",
"PTR",
"PX",
"RP",
"RT",
"SOA",
"TKEY",
"TSIG",
"TXT",
"WKS",
"X25"
);
foreach $i (@dnstypes) {
print "\nTrying $i Record Type ...\n";
$packet=$res->query($domain, $i);
if ($packet) {
    $packet->print;
    print "\n----------------------------------------------------------------------\n\n";
    }
}
}

sub get_activedir{
print "\nLooking for Active Directory SRV Records ...\n";
$res->usevc(0);
@srvtype=(
"_kerberos._tcp.Default-First-Site-Name._sites.dc._msdcs.",
"_kerberos._tcp.Default-First-Site-Name._sites.",
"_kerberos._tcp.dc._msdcs.",
"_kerberos._tcp.",
"_kerberos._udp.",
"_kpasswd._tcp.",
"_kpasswd._udp.",
"_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs.",
"_ldap._tcp.Default-First-Site-Name._sites.gc._msdcs.",
"_ldap._tcp.Default-First-Site-Name._sites.",
"_ldap._tcp.dc._msdcs.",
"_ldap._tcp.gc._msdcs.",
"_ldap._tcp.pdc._msdcs.",
"_ldap._tcp.",
"_gc._tcp.Default-First-Site-Name._sites.",
"_gc._tcp."
);
foreach $i (@srvtype) {
$service = $i.$domain;
print "\nTrying $service ...\n";
$packet=$res->query($service, 'SRV');
if ($packet) {
    $packet->print;
    print "\n----------------------------------------------------------------------\n\n";
   }
}
}

sub dig_dns{
print "\nStarting the DNS Digger ...\n";
@hybridlst1=("0","1","2","3","4","5","6","7","8","9");
@hybridlst2=("0","1","2","3","4","5","6","7","8","9");
$res->usevc(0);
if (open(NAMES,"names.txt")){
 while (<NAMES>){
        chomp($_);
        $host = $_.".".$domain;
        $packet=$res->query($host, 'ANY');
        if ($packet){
            $packet->print;
            print "\n----------------------------------------------------------------------\n\n";
        }
        if ($hybrid){
            foreach $h1 (@hybridlst1) {
            foreach $h2 (@hybridlst2) {
              $hybrid_host=$_.$h1.$h2.".".$domain;
              $packet=$res->query($hybrid_host, 'ANY');
              if ($packet){
                 $packet->print;
                 print "\n----------------------------------------------------------------------\n\n";
                 }
             }
            }
        }
        if ($silent){sleep 1};        
        }
     }
  else {print "Can't open names.txt!\n";}
close(NAMES);
}

sub usage(){
print "\nUsage: perl digg.pl <domain name> [OPTIONS]\n";
print "-----------------------------------------------------------\n";
print "OPTIONS:\n";
print "silent : Activates a time loop of 1 second in the DNS Digger function\n";
print "debug  : Starts a debug output\n";
print "nodig  : Disable the Digger\n";
print "port53 : Use Port 53 as Source Port\n";
print "host   : Use a specific DNS Server and must be followed by the IP Address\n";
print "hybrid : Appends 01 to 99 to the names while digging\n";
print "version: Try to get the DNS Server Version\n";
print "\nEXAMPLES:\n";
print "perl digg.pl example.com\n";
print "perl digg.pl example.com silent\n";
print "perl digg.pl example.com debug\n";
print "perl digg.pl example.com host 10.1.1.1\n";
exit;
}

# Main Programm
if (@ARGV==0){usage();}
$dig=1;
$root=1;
$version=0;
print "\n";
print "digg 0.3beta (c) 2003 by Michael Thumann (mthumann\@ernw.de)\n";
print "----------------------------------------------------------------------\n\n";
$res = Net::DNS::Resolver->new;
$res->tcp_timeout(5);
$res->udp_timeout(5);
$res->retry(2);
$res->retrans(3);
if (@ARGV==1){
   $domain=$ARGV[0];
   if (find_rootserver()){print "Done.\n";}
   else{print "Error: Can't connect to the DNS Server!\n";}
   }
if (@ARGV>=2){
   $domain=$ARGV[0];
   for ($o=1;$o<=@ARGV;$o++){    
       $option=$ARGV[$o];
       if ($option eq "silent") {$silent=1;print "Time Loop enabled!\n"}
       if ($option eq "debug") {$res->debug(1);print "Debug enabled!\n";}
       if ($option eq "port53") {$res->srcport(53);print "Switching to Source Port 53!\n";}
       if ($option eq "nodig") {$dig=0;print "Digger disabled!\n";}
       if ($option eq "version") {$version=1;print "Query DNS Server Version enabled!\n";}
       if ($option eq "hybrid") {$hybrid=1;print "Hybrid Mode for Digger enabled!\n";}
       if ($option eq "host") {
           $root=0;
           print "Use specific DNS Server!\n";
           $ns=$ARGV[$o+1];
       }
   }
   if ($root){    
      if (find_rootserver()){print "Done.\n";}
      else{print "Error: Can't connect to the DNS Server!\n";}
   }
   else{
      if (get_dns()){print "Done.\n";}
      else{print "Error: Can't connect to the DNS Server!\n";}
   }
   }
# end
