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

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, set_resolver
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, get_user_agents
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.data_mine import doc_start
from modules.bluto_logging import info
from modules.update import update, updateCheck

VERSION = "2.3.15"

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}  |  {12}

                 {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'), colored("MetaData Mining", 'green'))

if __name__ == "__main__":
    info('\nBluto Started')

    try:
        parser = argparse.ArgumentParser(description='Use: -e for lots of spinach (much larger sublist) | Use: -api for emailhunter_support')
        parser.add_argument('-e', help='Used for brute forcing with a very large list of SubDomains', required=False, action='store_true')
        parser.add_argument('-u', help='Used to check for updates', required=False, action='store_true')
        parser.add_argument('-t', type=int, help='Used to set the timeout, in seconds', required=False)
        parser.add_argument('-d', help='Used for setting the target domain', required=False)
        parser.add_argument('-api', help='Supply your free Email Hunter API key to gather even more email addresses', required=False)
        args = vars(parser.parse_args())
        if args['u']:
            info('Checking For Update')
            check, new_version = updateCheck()
            if check:
                info('Update Availble')
                print colored('Update Available!', 'red'), colored('{}'.format(new_version), 'green')
                print colored('Would you like to attempt to update?\n', 'green')
                answer = raw_input('Y|N: ')
                if answer in ('y', 'yes'):
                    update()
                    print '\n'
                else:
                    print '\n'
            else:
                print colored('You are running the latest version:','green'), colored('{}\n'.format(VERSION),'blue')

        if args['t']:
            timeout_value = args['t']
            myResolver = set_resolver(timeout_value)
        else:
            myResolver = dns.resolver.Resolver()
            myResolver.timeout = 10
            myResolver.lifetime = 10
            myResolver.nameservers = ['8.8.8.8', '8.8.4.4']

        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

        if args['d']:
            domain = args['d']
        else:
            domain = raw_input("Target Domain: ")
        user_agents = get_user_agents(USERAGENT_F)
        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, myResolver)
    #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 '\nGathering Data From Google, Bing And LinkedIn'
                userCountry, userServer = action_country_id(COUNTRIES_FILE, prox)
                action_bluto_use(userCountry)
                start_time_total = time.time()

                q1 = Queue.Queue()
                q2 = Queue.Queue()
                q3 = Queue.Queue()
                q5 = Queue.Queue()
                t1 = threading.Thread(target=action_google, args=(domain, userCountry, userServer, q1, user_agents, prox))
                t2 = threading.Thread(target=action_bing_true, args=(domain, q2, user_agents, prox))
                t3 = threading.Thread(target=action_linkedin, args=(domain, userCountry, q3, company, user_agents, prox))
                t5 = threading.Thread(target=doc_start, args=(domain, user_agents, prox, q5))
                start_time_email = time.time()
                if api:
                    q4 = Queue.Queue()
                    t4 = threading.Thread(target=action_emailHunter, args=(domain, api, user_agents, q4, prox)) #Takes domain[str], api[list], user_agents[list] #Returns email,url [list[tuples]] Queue[object], prox[str]
                    t4.start()
                    t4.join()
                else:
                    print colored('\nDon\'t forget you can increase your identified email count significantly with a free Hunter API key.\nhttps://hunter.io/api_keys', 'green')
                t1.start()
                t1.join()
                t2.start()
                t2.join()
                time_spent_email = time.time() - start_time_email
                t3.start()
                t3.join()
                start_download_time = time.time()
                t5.start()
                t5.join()
                time_spent_download = time.time() - start_download_time
                google_true_results = q1.get()
                bing_true_results = q2.get()
                linkedin_results = q3.get()
                data_mine = q5.get()
                start_time_brute = time.time()
                targets_t = action_brute_start(subs, myResolver)
                targets = action_brute_wild(targets_t, domain, myResolver)
                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, data_mine)
                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, data_mine)
            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 '\nGathering Data From Google, Bing And LinkedIn'
                userCountry, userServer = action_country_id(COUNTRIES_FILE, prox)
                action_bluto_use(userCountry)
                start_time_total = time.time()

                q1 = Queue.Queue()
                q2 = Queue.Queue()
                q3 = Queue.Queue()
                q5 = Queue.Queue()
                t1 = threading.Thread(target=action_google, args=(domain, userCountry, userServer, q1, user_agents, prox))
                t2 = threading.Thread(target=action_bing_true, args=(domain, q2, user_agents, prox))
                t3 = threading.Thread(target=action_linkedin, args=(domain, userCountry, q3, company, user_agents, prox))
                t5 = threading.Thread(target=doc_start, args=(domain, user_agents, prox, q5))
                start_time_email = time.time()
                if api:
                    q4 = Queue.Queue()
                    t4 = threading.Thread(target=action_emailHunter, args=(domain, api, user_agents, q4, prox)) #Takes domain[str], api[list], user_agents[list] #Returns email,url [list[tuples]] Queue[object], prox[str]
                    t4.start()
                    t4.join()
                else:
                    print colored('\nDon\'t forget you can increase your identified email count significantly with a free Hunter API key.\nhttps://hunter.io/api_keys', 'green')
                t1.start()
                t1.join()
                t2.start()
                t2.join()
                time_spent_email = time.time() - start_time_email
                t3.start()
                t3.join()
                start_download_time = time.time()
                t5.start()
                t5.join()
                time_spent_download = time.time() - start_download_time
                google_true_results = q1.get()
                bing_true_results = q2.get()
                linkedin_results = q3.get()
                data_mine = q5.get()
                start_time_brute = time.time()
                targets = action_brute_start(subs, myResolver)
                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, data_mine)
    #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, data_mine)
        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()
            q1 = Queue.Queue()
            q2 = Queue.Queue()
            q3 = Queue.Queue()
            q5 = Queue.Queue()
            t1 = threading.Thread(target=action_google, args=(domain, userCountry, userServer, q1, user_agents, prox))
            t2 = threading.Thread(target=action_bing_true, args=(domain, q2, user_agents, prox))
            t3 = threading.Thread(target=action_linkedin, args=(domain, userCountry, q3, company, user_agents, prox))
            t5 = threading.Thread(target=doc_start, args=(domain, user_agents, prox, q5))
            start_time_email = time.time()
            if api:
                q4 = Queue.Queue()
                t4 = threading.Thread(target=action_emailHunter, args=(domain, api, user_agents, q4, prox)) #Takes domain[str], api[list], user_agents[list] #Returns email,url [list[tuples]] Queue[object], prox[str]
                t4.start()
                t4.join()
            else:
                print colored('\nDon\'t forget you can increase your identified email count significantly with a free Hunter API key.\nhttps://hunter.io/api_keys', 'green')
            t1.start()
            t1.join()
            t2.start()
            t2.join()
            time_spent_email = time.time() - start_time_email
            t3.start()
            t3.join()
            start_download_time = time.time()
            t5.start()
            t5.join()
            time_spent_download = time.time() - start_download_time
            google_results = q1.get()
            bing_results = q2.get()
            linkedin_results = q3.get()
            data_mine = q5.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, data_mine)
            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, data_mine)

        info('Bluto Finished')
    except KeyboardInterrupt:
        print '\n\nRage Exit!..'
        info('Keyboard Interrupt From User\n')
        sys.exit()
