Last active
March 28, 2024 13:36
-
-
Save maesoser/4dd6a6f91d81f90064adc741137177c3 to your computer and use it in GitHub Desktop.
Simple dictionary based subdomain discovery tool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python3 | |
import dns.resolver | |
from tabulate import tabulate | |
from multiprocessing.dummy import Pool | |
from random import shuffle | |
import ipaddress, argparse | |
CEND = '\33[0m' | |
types = { | |
"A": '\33[32m', | |
"AAAA": '\33[32m', | |
"CAA": '\33[33m', | |
"CNAME": '\33[34m', | |
"MX": '\33[35m', | |
"NS": '\33[36m', | |
"SRV":'\33[93m', | |
"TXT":'\33[94m', | |
"PTR": '\33[32m', | |
"SRV": '\33[33m', | |
} | |
commonsubs = [ | |
"wap","new","docs","smtp2","smtp","ssl","gw","2tty","relay","office","dns2","upload","de","sms", | |
"mysql","sip","cdn","mail2","en","remote","govyty","blog","db","test2","services","calendar", | |
"hosting","cpanel","dns1","monitor","server","vpn","lyncdiscover","1rer","video","stat","cp", | |
"mssql","files","cloud","bbs","imap","images","helpdesk","ns4","store","gmail","www3","correo", | |
"www","ntp","proxy","email","intranet","mail1","lists","svn","radio","web1","jobs","my","ns1","test", | |
"support","mx","online","apps","mail","ns","library","dev","s","ww1","admin","ipv4","help","host", | |
"survey","ns2","hgfgdf","whm","webmail","ad","web","www2","ww","chat","service","nagios","live", | |
"www1","static","stats","api","dns","old","webdisk","forum","img","secure","autoconfig","staging", | |
"irc","tv","forums","owa","cms","gateway","mx1","media","app","home","2","pop3","i","info","exchange", | |
"news","moodle","mx2","stage","extranet","beta","search","backup","newsletter","crm","vps","start", | |
"ldap","data","it","portal","dns3","localhost","blogs","ads","lkjkui","ww42","ns3","sites","www4", | |
"cs","sql","shop","1","demo","ns5","gov","ftp","autodiscover","web2","mail3","mobile","login","wiki", | |
"download","ftp2","m","panel","pop", | |
] | |
nameservers = [ | |
"1.0.0.1", "1.1.1.1", # Cloudflare | |
"8.8.4.4", "8.8.8.8", # Google | |
"208.67.222.222", "208.67.220.220", # XX | |
"9.9.9.9", "149.112.112.112", # Quad | |
"64.6.64.6", "64.6.65.6" # xx | |
] | |
def getASNinfo(addr): | |
info = {} | |
try: | |
ip = ipaddress.ip_address(addr) | |
except Exception as e: | |
return info | |
ip = ".".join(reversed(str(ip).split('.'))) | |
ipinfo = dig("{}.origin.asn.cymru.com".format(ip), 'TXT') | |
if len(ipinfo) == 0: | |
return info | |
ipinfo = ipinfo[0].replace("\"","").replace(" ","") | |
info = { | |
"as": ipinfo.split("|")[0], | |
"prefix": ipinfo.split("|")[1], | |
"country": ipinfo.split("|")[2] | |
} | |
asninfo = dig("AS{}.asn.cymru.com".format(info['as']), 'TXT') | |
if len(asninfo) == 0: | |
return info | |
asninfo = asninfo[0].replace("\"","").replace(" ","") | |
info["name"] = asninfo.split("|")[-1] | |
return info | |
def dig(target, type): | |
resolver = dns.resolver.Resolver() | |
resolver.use_edns(0,dns.flags.DO,4096) | |
shuffle(nameservers) | |
resolver.nameservers = nameservers | |
resolver.timeout = 3 | |
resolver.lifetime = 3 | |
try: | |
result = resolver.resolve(target, type) | |
except dns.exception.DNSException as e: | |
return [] | |
response = [x.to_text() for x in result] | |
response.sort() | |
return response | |
def sdig(domain): | |
out = [] | |
for t in types: | |
response = dig(domain, t) | |
for item in response: | |
info = {} | |
if t in ['A', 'AAAA']: | |
info = getASNinfo(item) | |
out.append([ | |
domain, | |
"{}{}{}".format(types[t],t,CEND), | |
info.get('as'), | |
info.get('name'), | |
item | |
] | |
) | |
return out | |
def get_args(): | |
parser = argparse.ArgumentParser(description="Dictionary based DNS discovery tool") | |
parser.add_argument('--resolver', required=False, help='DNS Resolver', default="1.0.0.1") | |
parser.add_argument('--threads', required=False, help='DNS Resolver', default=16) | |
parser.add_argument('domain') | |
args = parser.parse_args() | |
return args | |
args = get_args() | |
headers = ["Key", "Type", 'AS', 'Name', "Value" ] | |
domains = [ args.domain ] | |
domains += ["{}.{}".format(sub, args.domain) for sub in commonsubs] | |
shuffle(domains) | |
pool = Pool(args.threads) | |
table = pool.map(sdig, domains) | |
pool.close() | |
pool.join() | |
table = [x for xs in table for x in xs] | |
print(tabulate(table, headers=headers)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment