#!/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)