#! /usr/local/bin/perl
$|=1;

### TLD EXP (pubic version) for BigRed Framework
###
### USAGE: perl exp-tld.pl In_file Out_file
### In_file is domains
### Out_file is domains (expanded to all other TLDs and sub TLDs)
### SensePost 2003/09 (rt)
###
###

if ($#ARGV < 1) {die "perl exp-tld.pl In_file (domains) Out_file (all domains)";}

open (IN,"@ARGV[0]") || die "Cant read input file\n";
while (<IN>) {
	chomp;	push @domains,piecedomain($_);
}
close (IN);
@domains=dedupe(@domains);

$nameserver="196.4.160.2";
######### ^^^^^^^^^^^^^^^^^ ###########
############ please change ############

$DNSTIMEOUT=3;
$DNSRETRY=2;

@TLDS=&loadTLDS();
@TLDS=sort(@TLDS);
@OTHERS=&loadsubTLDS;

$baselinedomain="bigred-control-sp";
$baselinedomain2="redbig-control-sp";

foreach $tld (@TLDS){
	foreach $domain (@domains) {
		foreach $sub (@OTHERS){
			if (length($sub) > 0){
				$workdomain = $domain.".".$sub.".".$tld;
				$fwork=$baselinedomain.".".$sub.".".$tld;
				$fwork2=$baselinedomain2.".".$sub.".".$tld;

			}
			else {
				$workdomain = $domain.".".$tld;
				$fwork=$baselinedomain.".".$tld;
				$fwork2=$baselinedomain2.".".$tld;
			}
			
			print "Working on [$workdomain]\n";	
	
			$result = `nslookup -timeout=3 -retry=2 -query=ANY $workdomain 2>&1`;
			if (($result =~ /answer/i) || ($result =~ /internet address/)){
				
				undef @fakemxnet; undef @realmxnet;
				undef @fakeaanet; undef @realaanet;

				undef @mxes; undef @realmxes;
				undef @aaes; undef @realaaes;
			
			
				### determine the networks of the fake MX records
				@mxes=mxlookup($fwork,0);
				push @mxes,&mxlookup($fwork2,0);
				@mxes=dedupe(@mxes);

				foreach $fmx (@mxes){
					push @fakemxnet,findnet($fmx);
				}

				# determine the real MX records
				@realmxes=mxlookup($workdomain);
				foreach $rmx (@realmxes){
					push @realmxnet,findnet($rmx);
				}

				# check if there's a match
				$mxflag=0;
				foreach $rmxnet (@realmxnet){
					foreach $fmxnet (@fakemxnet){
						if ($rmxnet eq $fmxnet){
							$mxflag=1;
							last;
						}				
					}
					if ($mxflag==1){last;}
				}



				###
				### determine the networks of the fake A records
				@aaes=forward($fwork,0);
				push @aaes,&forward($fwork2,0);
				@aaes=dedupe(@aaes);

				foreach $fa (@aaes){
					push @fakeaanet,findnet($fa);
				}

				# determine the real A records
				@realaaes=forward($workdomain);
				foreach $ra (@realaaes){
					push @realaanet,findnet($ra);
				}

				# check if there's a match
				$aflag=0;
				foreach $ranet (@realaanet){
					foreach $fanet (@fakeaanet){
						if ($ranet eq $fanet){
							$aflag=1;
							last;
						}				
					}
					if ($aflag==1){last;}
				}


				if (($aflag == 0) && ($mxflag == 0)){
					logger(1,"$workdomain\n");
				} 
			}
		}
	}
}
close (OUT);



sub dedupe
{
        (@keywords) = @_;
        my %hash = ();
        foreach (@keywords) {
                $_ =~ tr/[A-Z]/[a-z]/;
                chomp;
                if (length($_)>1){$hash{$_} = $_;}
        }
        return keys %hash;
}

sub findnet
{
        $classc = "";
        ($iptouse) = @_;
        if (!($iptouse =~ /127.0.0.1/))
        {
                @splitter=split(/\./,$iptouse);
                $classc=@splitter[0].".".@splitter[1].".".@splitter[2];
        }
        return ($classc);  
}

sub forward {
        ($passed,$mode)=@_;
        undef @returns;
        @nslookupout=`nslookup -timeout=$DNSTIMEOUT -retry=$DNSRETRY $passed $nameserver 2>&1;`;
        my $flag=0;
        foreach $line (@nslookupout){
                if (($line =~ /$passed/) && ($line !~ /can't find/)){$flag=1;}
                if ($line =~ /Address/){
                        ($duh,$returner,@crap)=split(/s: /,$line);
                }
        }
        $returner=~s/ //g;
        if ($flag==1){
                @ips=split(/,/,$returner);
                foreach $ips (@ips){
                        chomp $ips;
                        $ips=~s/ //g;
                        $passed=~s/ //g;
                        $tosave=$ips;
                        if ($mode==0){push @returns,$tosave;}
                        if ($mode==1){
                                $work=$passed.";".$tosave;
                                push @returns,$work;
                        }
                        if ($mode==2){
                                $work=$passed.";".$tosave.";FL";
                                push @returns,$work;
                        }

                }
        }
        return @returns;          
}


sub mxlookup {
        undef @returns;
        ($passed,$mode)=@_;       
        @nslookupout=`nslookup -timeout=$DNSTIMEOUT -retry=$DNSRETRY -query=MX $passed $nameserver 2>&1;`;

        ## get the nameservers - we have to exclude them
        foreach $line (@nslookupout){
                if ($line =~ /nameserver =/){
                        ($duh,$nameserv)=split(/= /,$line);
                        push @nameservers,$nameserv;
                }
        }

        ## get mailexchangers - we have to include them
        foreach $line (@nslookupout){
                if ($line =~ /mail exchanger/i){
                        ($duh,$duh,$mailserv)=split(/= /,$line);
                        push @mailservers,$mailserv;
                }
        }
        foreach $line (@nslookupout){
                if ($line =~ /internet address/){

                        $nsflag=0;
                        foreach $ns (@nameservers){
                                chomp $ns;
                                if ($line =~ /$ns/){$nsflag=1;}
                        }
                        foreach $ms (@mailservers){
                                chomp $ms;
                                if ($line =~ /$ms/){$nsflag=0;}
                        }

                        if ($nsflag==0){
                                ($duh,$returner)=split(/= /,$line);
                                ($name,@crap)=split(/   /,$duh);
                                chomp $name; chomp $returner;
                                $tosave=$returner;
                                if ($mode ==0){push @returns,$tosave;}
                                if ($mode ==1){
                                        $work = $name.";".$tosave;
                                        push @returns,$work;
                                }
                                if ($mode ==2){
                                        $work = $name.";".$tosave.";MX";
                                        push @returns,$work;
                                }

                        }
                }                 
        }
        return @returns;
}


sub loadTLDS{
@xTLDS=(
"com","org","net","edu","mil","gov","uk","af","al","dz","as",
"ad","ao","ai","aq","ag","ar","am","aw","ac","au","at",
"az","bs","bh","bd","bb","by","be","bz","bj","bm","bt",
"bo","ba","bw","bv","br","io","bn","bg","bf","bi","kh",
"cm","ca","cv","ky","cf","td","cl","cn","cx","cc","co",
"km","cd","cg","ck","cr","ci","hr","cu","cy","cz","dk",
"dj","dm","do","tp","ec","eg","sv","gq","er","ee","et",
"fk","fo","fj","fi","fr","gf","pf","tf","ga","gm","ge",
"de","gh","gi","gr","gl","gd","gp","gu","gt","gg","gn",
"gw","gy","ht","hm","va","hn","hk","hu","is","in","id",
"ir","iq","ie","im","il","it","jm","jp","je","jo","kz",
"ke","ki","kp","kr","kw","kg","la","lv","lb","ls","lr",
"ly","li","lt","lu","mo","mk","mg","mw","my","mv","ml",
"mt","mh","mq","mr","mu","yt","mx","fm","md","mc","mn",
"ms","ma","mz","mm","na","nr","np","nl","an","nc","nz",
"ni","ne","ng","nu","nf","mp","no","om","pk","pw","pa",
"pg","py","pe","ph","pn","pl","pt","pr","qa","re","ro",
"ru","rw","kn","lc","vc","ws","sm","st","sa","sn","sc",   
"sl","sg","sk","si","sb","so","za","gz","es","lk","sh",
"pm","sd","sr","sj","sz","se","ch","sy","tw","tj","tz",
"th","tg","tk","to","tt","tn","tr","tm","tc","tv","ug",
"ua","ae","gb","us","um","uy","uz","vu","ve","vn","vg",
"vi","wf","eh","ye","yu","za","zr","zm","zw","int","gs",
"info","biz","su","name","coop","aero");

return(dedupe(@xTLDS));
}

sub loadsubTLDS{
@xsubTLDS=("","com","co","ac","org","net","gov","mil");
return(@xsubTLDS);
}

sub piecedomain{

        ($passed)=@_;
        @TLDS=loadTLDS();
        @OTHERS=loadsubTLDS();

        #find what TLD we are in and remove it
        @parts=split (/\./,$passed);
        $lastpart=@parts[$#parts];
        foreach $tld (@TLDS){
                if ($tld eq $lastpart){
                        ($yeah,$crap)=split(/\.$tld/,$passed);
                        last;
                }
        }

        @parts=split (/\./,$yeah);
        $lastpart=@parts[$#parts];
        foreach $other (@OTHERS){
                if ($other eq $lastpart){
                        ($yeah,$crap)=split(/\.$other/,$yeah);
                        last;
                }
        }
        return ("$yeah");
}

########## logger (new from MH)
sub logger{
        ($filer,$towrite)=@_;

        if($filer =~ /^\D/){$filer = $filer;}
        else{$filer = $ARGV[$filer];}

        open (OUT,">>$filer") || die "Cannot open file $filer for appending\n";
        print OUT $towrite;
        close (OUT)
}

# spidermark: tldexp