DNS 2 GeoIP is a simple python script that brute forces DNS and subsequently geolocates the found subdomains. It is useful for determining which services a company hosts off site or on site during a penetration test.
12f04939eaa592462e7f86a13519994bcc657009b29709b32e4d4208459afcf8
#!/usr/bin/env python
#Packaged dependencies
#apt-get install python-geoip python-dnspython python-argparse
#Unpackaged dependencies
#simplekml
#hg clone https://code.google.com/p/simplekml/
#mv simplekml simplekml.hg
#mv simplekml.hg/simplekml simplekml
#rm -Rf simplekml.hg
#City resolution GeoLite database
#wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
#gunzip GeoLiteCity.dat.gz
#sudo mv GeoLiteCity.dat /usr/share/GeoIP/GeoIPCity.dat
#special thanks to andrew king for helping me turn a ugly hack that didn't work into clean code that carries out a useful function
#this tool geolocates subdomains for any given domain i reccomend you use it to scope out a network
#to see which services they run on site and which they run offiste
import GeoIP
import dns.resolver
import argparse
import simplekml
class DnsDictSearch:
def __init__(self, path_to_wordlist):
self.kml = simplekml.Kml()
self.path_to_wordlist = path_to_wordlist
self.gi = GeoIP.open(path_to_dat,GeoIP.GEOIP_STANDARD)
def to_kml(self, coords, out):
for coord in coords:
self.kml.newpoint(name=coord[0],
coords=[coord[1]]
)
self.kml.save(out)
def brute(self, domain, path_to_dat, path_to_output):
coords = []
with open(self.path_to_wordlist, "r") as lines:
try:
for line in lines.readlines():
fulldomain = line.rstrip() + "." + domain
try:
answers = dns.resolver.query(fulldomain, 'A')
if type(answers) == dns.resolver.Answer:
for rdata in answers:
ip = rdata.address
gi = GeoIP.open(path_to_dat,GeoIP.GEOIP_STANDARD)
go = gi.record_by_addr(ip)
coord = (go['latitude'], go['longitude'])
coords.append([fulldomain, coord])
except:
pass
except (dns.exception.DNSException):
pass
self.to_kml(coords, path_to_output)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=''+\
'brute forces subdomains and then geolocates the subdomains it finds')
parser.add_argument('-D',
action='store',
dest='domain',
help='the domain you wish to analyze',
default='This is not a domain')
parser.add_argument('-w',
action='store',
dest='path_to_wordlist',
help='the full path to the list of possible subdomains'+\
' for bruteforce',
default='This is not a wordlist')
parser.add_argument('-x',
action='store',
dest='path_to_dat',
help='the path to the max mind geoip dat file'+\
' (/usr/share/GeoIP/GeoIPCity.dat being the default)',
default ='/usr/share/GeoIP/GeoIPCity.dat')
parser.add_argument('-o',
action='store',
dest='path_to_output',
help='saves subdomain locations to a kml file',
default='output.kml')
results = parser.parse_args()
run_warnings = []
if results.domain != 'This is not a domain':
domainarg = results.domain
else:
run_warnings.append("You need to specify a domain with -D")
if results.path_to_wordlist != 'This is not a wordlist':
wordarg = results.path_to_wordlist
else:
run_warnings.append("You need to specify a wordlist with -w")
datarg = results.path_to_dat
kmlarg = results.path_to_output
if run_warnings.__len__() > 0:
print("You failed to supply some required arguments")
for warn in run_warnings:
print(warn)
else:
this = DnsDictSearch(wordarg)
this.brute(domainarg,datarg,kmlarg)