#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import sys
import site
import os

SITES = site.getsitepackages()
for item in SITES:
    if os.path.exists(item + "/Bluto/modules/__init__.py"):
        path = item
        sys.path.append(path + '/Bluto/')

FILENAME_1 = path + "/Bluto/doc/subdomains-top1mil-20000.txt"
FILENAME_2 = path + "/Bluto/doc/sub_interest.txt"
USERAGENT_F = path + "/Bluto/doc/user_agents.txt"
COUNTRIES_FILE = path + "/Bluto/doc/countries.txt"
INFO_LOG_FILE = os.path.expanduser('~/Bluto/log/bluto-info.log')
ERROR_LOG_FILE = os.path.expanduser('~/Bluto/log/bluto-error.log')

import time
import threading
import Queue
import argparse
import dns.resolver
import dns.query
import dns.zone
from termcolor import colored
from modules.get_dns import action_brute_start, action_wild_cards, action_zone_transfer, get_dns_details, action_brute_wild
from modules.search import action_bing_true, action_google, action_linkedin, action_netcraft, action_emailHunter
from modules.get_file import get_subs, get_sub_interest, get_line_count
from modules.general import action_country_id, action_whois, action_bluto_use, check_dom
from modules.output import action_output_vuln_zone, action_output_wild_false, action_output_wild_false_hunter, action_output_vuln_zone_hunter
from modules.bluto_logging import info, error


VERSION = "2.01"
myResolver = dns.resolver.Resolver()
myResolver.timeout = 6
myResolver.lifetime = 6
myResolver.nameservers = ['8.8.8.8', '8.8.4.4']
prox = False

for item in SITES:
    if os.path.exists(item + "/Bluto/doc/subdomains-top1mil-20000.txt"):
        path = item
        info('Application Path Identified: ' + path)
    else:
        pass

print """
 BBBBBBBBBBBBBBBBB  lllllll                       tttt
 B::::::::::::::::B l:::::l                     ttt:::t
 B::::::BBBBBB:::::Bl:::::l                     t:::::t
 BB:::::B     B:::::l:::::l{6}                t:::::t
   B::::B     B:::::Bl::::luuuuuu    uuuuuttttttt:::::ttttttt      ooooooooooo
   B::::B     B:::::Bl::::lu::::u    u::::t:::::::::::::::::t    oo:::::::::::oo
   B::::BBBBBB:::::B l::::lu::::u    u::::t:::::::::::::::::t   o:::::::::::::::o
   B:::::::::::::BB  l::::lu::::u    u::::tttttt:::::::tttttt   o:::::ooooo:::::o
   B::::BBBBBB:::::B l::::lu::::u    u::::u     t:::::t         o::::o     o::::o
   B::::B     B:::::Bl::::lu::::u    u::::u     t:::::t         o::::o     o::::o
   B::::B     B:::::Bl::::lu::::u    u::::u     t:::::t         o::::o     o::::o
   B::::B     B:::::Bl::::lu:::::uuuu:::::u     t:::::t    ttttto::::o     o::::o
 BB:::::BBBBBB::::::l::::::u:::::::::::::::uu   t::::::tttt:::::o:::::ooooo:::::o
 B:::::::::::::::::Bl::::::lu:::::::::::::::u   tt::::::::::::::o:::::::::::::::o
 B::::::::::::::::B l::::::l uu::::::::uu:::u     tt:::::::::::ttoo:::::::::::oo
 BBBBBBBBBBBBBBBBB  llllllll   uuuuuuuu  uuuu       ttttttttttt    ooooooooooo

  {2} | {3} | {4} | {9}
        {8} | {7} | {10}
                       {11}

              {0}  |  {1}
                  {5}
""" . format (colored("Author: Darryl Lane", 'blue'), colored("Twitter: @darryllane101", 'blue'), colored("DNS Recon", 'green'), colored("SubDomain Brute Forcer", 'green'), colored("DNS Zone Transfers", 'green'), colored("https://github.com/darryllane/Bluto", 'green'), colored("v" + VERSION, 'red'), colored("Email Enumeration", 'green'), colored("Staff Enumeration", 'green'), colored("DNS Wild Card Checks", 'green'), colored("DNS Wild Card Brute Forcer", 'green'), colored("Compromised Account Enumeration", 'green'))

if __name__ == "__main__":
    info('\nBluto Started')
    try:
        parser = argparse.ArgumentParser(description='Use: -E for lots of spinach | Use: -api for emailhunter_support')
        parser.add_argument('-E', help='Used for brute forcing with a very large list of SubDomains', required=False)
        parser.add_argument('-api', help='Supply your free Emial Hunter API key to gather even more email addresses', required=False)
        args = vars(parser.parse_args())
        if args['E']:
            info('-E Argument Used')
            FILENAME_1 = path + "/Bluto/doc/lots-of-spinach.txt"
        if args['api']:
            api = args['api']
            info('-api Argument Used with api: ' + str(api))
        else:
            api = False
        domain = raw_input("Target Domain: ")
        info('Domain Identified: ' + str(domain))
        domain_r = domain.split('.')
        report_location = os.path.expanduser('~/Bluto/Bluto-Evidence-{}.html'.format(domain_r[0]))
    #Check if domain valid
        check_dom(domain)
    #WhoisGet
        company = action_whois(domain)
    #Detail Call
        sub_intrest = get_sub_interest(FILENAME_2, domain)
        zn_list = get_dns_details(domain, myResolver)
    #NetCraft Call
        netcraft_list = action_netcraft(domain, myResolver)
    #ZoneTrans Call
        vulnerable_results = action_zone_transfer(zn_list, domain)
        if vulnerable_results == ([], []):
            print "\nNone of the Name Servers are vulnerable to Zone Transfers"
    #Bruting
            print '\nTesting For Wild Cards'
            value = action_wild_cards(domain, myResolver)
            if value == True:
                print colored('\n\tWild Cards Are In Place', 'green')
                print colored("\n\tOh no! You ain't eatin' no spinach in this picture", 'blue')
                print colored("\n\nThis Will Take A While Longer, On Average +- 20min", 'grey')
                check_count = get_line_count(FILENAME_1)
                subs = get_subs(FILENAME_1, domain)
                print '\nBrute Forcing Sub-Domains\n\n\tWhile you are waiting we will gather email addresses\n\tand LinkedIn users'
                print '\nGathering Data From Google, Bing And LinkedIn'
                userCountry, userServer = action_country_id(COUNTRIES_FILE, prox)
                action_bluto_use(userCountry)
                start_time_total = time.time()
                start_time_email = time.time()
                if api:
                    q4 = Queue.Queue()
                    t4 = threading.Thread(target=action_emailHunter, args=(domain, api, USERAGENT_F, q4, prox)) #Takes domain[str], api[list], USERAGENT_F[list] #Returns email,url [list[tuples]] Queue[object], prox[str]
                    t4.start()
                q1 = Queue.Queue()
                q2 = Queue.Queue()
                q3 = Queue.Queue()
                t1 = threading.Thread(target=action_google, args=(domain, userCountry, userServer, q1, USERAGENT_F, prox))
                t2 = threading.Thread(target=action_bing_true, args=(domain, q2, USERAGENT_F, prox))
                t3 = threading.Thread(target=action_linkedin, args=(domain, userCountry, q3, company, USERAGENT_F, prox))
                t1.start()
                t2.start()
                t3.start()
                if api:
                    t4.join()
                t1.join()
                t2.join()
                t3.join()
                time_spent_email = time.time() - start_time_email
                google_true_results = q1.get()
                bing_true_results = q2.get()
                linkedin_results = q3.get()
                start_time_brute = time.time()
                targets_t = action_brute_start(subs)
                targets = action_brute_wild(targets_t, domain)
                time_spent_brute = time.time() - start_time_brute
                time_spent_total = time.time() - start_time_total
                if targets == []:
                    targets.append("temp-enter")
                domains = list(set(targets + netcraft_list))
                domains.sort()
                if "temp-enter" in domains: domains.remove("temp-enter")
                brute_results_dict = dict((x.split(' ') for x in domains))
    #Outputing data
                if api:
                    emailHunter_results = q4.get()
                    action_output_wild_false_hunter(brute_results_dict, sub_intrest, google_true_results, bing_true_results, linkedin_results, check_count, domain, time_spent_email, time_spent_brute, time_spent_total, emailHunter_results, args, report_location, company)
                else:
                    action_output_wild_false(brute_results_dict, sub_intrest, google_true_results, bing_true_results, linkedin_results, check_count, domain, time_spent_email, time_spent_brute, time_spent_total, report_location, company)
            else:
                print colored('\n\tWild Cards Are Not In Place', 'red')
                check_count = get_line_count(FILENAME_1)
                subs = get_subs(FILENAME_1, domain)
                print '\nBrute Forcing Sub-Domains\n\n\tWhile you are waiting we will gather email addresses\n\tand LinkedIn users'
                print '\nGathering Data From Google, Bing And LinkedIn'
                userCountry, userServer = action_country_id(COUNTRIES_FILE, prox)
                action_bluto_use(userCountry)
                start_time_total = time.time()
                start_time_email = time.time()
                q1 = Queue.Queue()
                q2 = Queue.Queue()
                q3 = Queue.Queue()
                if api:
                    q4 = Queue.Queue()
                    t4 = threading.Thread(target=action_emailHunter, args=(domain, api, USERAGENT_F, q4, prox)) #Takes domain[str], api[list], USERAGENT_F[list] #Returns email,url [list[tuples]] Queue[object], prox[str]
                    t4.start()
                t1 = threading.Thread(target=action_google, args=(domain, userCountry, userServer, q1, USERAGENT_F, prox))
                t2 = threading.Thread(target=action_bing_true, args=(domain, q2, USERAGENT_F, prox))
                t3 = threading.Thread(target=action_linkedin, args=(domain, userCountry, q3, company, USERAGENT_F, prox))
                t1.start()
                t2.start()
                t3.start()
                if api:
                    t4.join()
                t1.join()
                t2.join()
                t3.join()
                time_spent_email = time.time() - start_time_email
                google_true_results = q1.get()
                bing_true_results = q2.get()
                linkedin_results = q3.get()
                start_time_brute = time.time()
                targets = action_brute_start(subs)
                time_spent_brute = time.time() - start_time_brute
                time_spent_total = time.time() - start_time_total
    #Clean Brute Results
                if targets == []:
                    targets.append("temp-enter")
                domains = list(set(targets + netcraft_list))
                domains.sort()
                if "temp-enter" in domains: domains.remove("temp-enter")
                brute_results_dict = dict((x.split(' ') for x in domains))
                if api:
                    emailHunter_results = q4.get()
                    action_output_wild_false_hunter(brute_results_dict, sub_intrest, google_true_results, bing_true_results, linkedin_results, check_count, domain, time_spent_email, time_spent_brute, time_spent_total, emailHunter_results, args, report_location, company)
    #Outputing data
                else:
                    action_output_wild_false(brute_results_dict, sub_intrest, google_true_results, bing_true_results, linkedin_results, check_count, domain, time_spent_email, time_spent_brute, time_spent_total, report_location, company)
        else:
    #Vuln Zone Trans
            vulnerable_list = vulnerable_results[0]
            clean_dump = vulnerable_results[1]
            print '\nGathering Data From Google, Bing And LinkedIn'
            userCountry, userServer = action_country_id(COUNTRIES_FILE, prox)
            action_bluto_use(userCountry)
            start_time_total = time.time()
            start_time_email = time.time()
            q1 = Queue.Queue()
            q2 = Queue.Queue()
            q3 = Queue.Queue()
            if api:
                q4 = Queue.Queue()
                t4 = threading.Thread(target=action_emailHunter, args=(domain, api, USERAGENT_F, q4, prox)) #Takes domain[str], api[list], USERAGENT_F[list] #Returns email,url [list[tuples]] Queue[object], prox[str]
                t4.start()
            t1 = threading.Thread(target=action_google, args=(domain, userCountry, userServer, q1, USERAGENT_F, prox))
            t2 = threading.Thread(target=action_bing_true, args=(domain, q2, USERAGENT_F, prox))
            t3 = threading.Thread(target=action_linkedin, args=(domain, userCountry, q3, company, USERAGENT_F, prox))
            t1.start()
            t2.start()
            t3.start()
            t1.join()
            t2.join()
            t3.join()
            if api:
                t4.join()
            time_spent_email = time.time() - start_time_email
            google_results = q1.get()
            bing_results = q2.get()
            linkedin_results = q3.get()
            time_spent_total = time.time() - start_time_total
    #Outputing data
            if api:
                emailHunter_results = q4.get()
                action_output_vuln_zone_hunter(google_results, bing_results, linkedin_results, time_spent_email, time_spent_total, clean_dump, sub_intrest, domain, emailHunter_results, args, report_location, company)
            else:
                action_output_vuln_zone(google_results, bing_results, linkedin_results, time_spent_email, time_spent_total, clean_dump, sub_intrest, domain, report_location, company)

        info('Bluto Finished')
    except KeyboardInterrupt:
        print '\n\nExiting..'
        error('Keyboard Interrupt From User\n')
        sys.exit()
