#!/usr/bin/perl#
################
### DNScan ######################
################ Inspired by ###
### strayfe's dmap ####################
###################### Coded by dbr ###
### 01/09/2006 ###
####################
use Socket;
use Getopt::Std;
use strict;
use Thread;
$SIG{INT} = \&clearup;
#Varible used to check a second sigint, if it's setup in the sub, it's killed when the thread ends
#it'd declared out here so I can set/check it without it being killed
my$clearingup;
#################
###! Default !#################
#################! Options !###################
#################! Change me !###
###################
##Lookup delay,
# Sets the delay between lookups, to stop a craptonne of looksups at once
## Over-ride with -d
my $delay=1;
##Default prefix file
# Sets the default prefix file if none is set
## Over-ride with -p
my $prefile="prefixs.txt";
##Try numeric increments
# If a subdomain is valid, try subdomain + number,
# Example : db.example.com is not valid, db1.example.com is valid
# try db2.example.com, if it's valid, try db3.example.com etc etc
# Will try regardless of subdomain without number (incase db is invalid, but db1 is)
## Default : True
## Over-ride with -i
my $increment="false";
##Verbose
# Extra errors
## Default : False
## Over-ride with : -v
my $verbose="false";
##Max threads
# Number of threads to run at once
## Default : 10
## Over-ride with -t
my $maxthread=10;
##################### #######################
# \/ Don't touch \/ ############################## end user varibles #
##################### Unless you know your doing #####################
##############################
#commandline switches-y bit
#not defining v and i makes them work with no data
# after, for some screwed up reason, thus they aren't there..
getopt("p:d:h:");
our($opt_i,$opt_h,$opt_v,$opt_p,$opt_d);
if($opt_v){
$verbose="true";
}else{
if($verbose eq "true"){
warn("[?] Using default verbose\n");
$verbose="true";
}else{
if($verbose eq "false"){
undef $verbose;
}else{
warn("[?]Default verbose is not true/false, defaulting to not-verbose");
undef($verbose);
}
}
};if($verbose){warn("[?] Verbose\n");}
$prefile=$opt_p || warn("[?] using default prefix file : " . $prefile ."\n") if $verbose;
$delay=$opt_d || warn "[?] using default delay : " .$delay."\n" if $verbose;
if($opt_i){
$increment=$opt_i;
warn("[?] Using increment\n");
} else {
if($increment eq "true"){
warn("[?] using incremented subdomains (default)\n") if $verbose;
} else {
if($increment eq "false"){
undef($increment);
} else {
warn("[?] default increment not true/false, defaulting to false\n");
undef($increment);
}
}
}
my $host=$opt_h || usage("host must be set");
#Open prefix file
open(PRE,"<".$prefile);
chomp(my @prefixs=<PRE>);
close(PRE);
#file checks
if(!-e $prefile){
usage("prefix file does not exist");
}
print("[*] Number of prefixs : " . $#prefixs . "\n");
#end startup crap, bulk of code from here on
my @threads;
my $thrnum=0;
if($increment){
my @increment_curnum;
my @increment_origname;
}
my @results;
for my $prefix (@prefixs)
{
my @templist;
while(1){
@templist=Thread->list;
if($#templist<10){
@threads[$thrnum]=new Thread (\&scanthread,$prefix,$host,$increment);
my $nullinglypointless=@threads[$thrnum]->join();
$thrnum++;
sleep(0.5);
last;
} else {
sleep(1);
}
}
}
sleep(1);
print("[*] Done all lookups\n[*] Displaying results\n");
print($#results);
exit;
# # # # # # # # # #
# # thread code # #
# # # # # # # # # #
sub scanthread(){
my ($name,$host,$increment)=@_;
if($increment){
if(!(@main::increment_curnum[$name])){
my @data;
push(@data,"2");
push(@data,$name);
@main::increment_curnum[$name]=@data;
}
}
print("\n".$name.".".$host.":\n");
my $tolookup=$name .".". $host;
my @addrs=namelookup($tolookup);
if($#addrs>=0){
#subdomain exists
if($increment){
my $incrementname=$name . ((@main::increment_curnum[$name]))[0];
print("Trying increment of " . ((@main::increment_curnum[$name])[0])."\n");
@main::threads[$#main::threads++]=new Thread(\&scanthread,$incrementname,$host,$increment);
((@main::increment_curnum[$name]))++;
}
my @topush;
(@topush[$name])=@addrs;
push((@main::results),@topush);
return "true";
} else {
#Subdomain doesn't exist
return "false";
}
}
# # # # # # #
# # subs # #
# # # # # # #
#simple dns lookup
sub namelookup(){
my ($lookupname)=@_;
my @addrs;
my @gethost=(gethostbyname($lookupname))[4];
if($#gethost>=0){
for(@gethost){
my $curip=inet_ntoa($_);
push(@addrs,$curip);
}
}
return @addrs;
}
#usage error sub
sub usage(){
my ($message)=@_;
warn("[!] ". $message . "\n\n");
print("Usage : ".$0." [OPTIONS]\n");
print("-p \t Prefix file. \t\t\t\tDefault: prefix
-d \t Delay between lookups in seconds. \tDefault : 1
-i \t Try incrementing subdomain. \tDefault : True\n\t\t This will try subdomain + 1, if it's valid, then 2, etc, till they are no longer valid\n
-h \t The target hostname \t Default : None
\t This is the host to try subdomains on, should be in the format name.tld, no www.");
exit;
}
sub clearup(){
if($main::clearingup eq "true"){die("[!] Caught second SIGINT\n");}
$main::clearingup="true";
warn("[!] Caught SIGINT, cleaning up\n");
if(@threads){
for(Thread->list){
$_->kill("SIGINT");
}
}
if(@prefixs){
close(@prefixs);
}
}