| 
 | 1 | +import requests  | 
 | 2 | +from threading import Thread, active_count  | 
 | 3 | +from queue import Queue  | 
 | 4 | +import time  | 
 | 5 | + | 
 | 6 | +q = Queue()  | 
 | 7 | + | 
 | 8 | +def scan_subdomains(domain):  | 
 | 9 | +    global q  | 
 | 10 | +    while True:  | 
 | 11 | +        # get the subdomain from the queue  | 
 | 12 | +        subdomain = q.get()  | 
 | 13 | +        # scan the subdomain  | 
 | 14 | +        url = f"http://{subdomain}.{domain}"  | 
 | 15 | +        try:  | 
 | 16 | +            requests.get(url)  | 
 | 17 | +        except requests.ConnectionError:  | 
 | 18 | +            pass  | 
 | 19 | +        else:  | 
 | 20 | +            print("[+] Discovered subdomain:", url)  | 
 | 21 | + | 
 | 22 | +        # we're done with scanning that subdomain  | 
 | 23 | +        q.task_done()  | 
 | 24 | + | 
 | 25 | + | 
 | 26 | +def main(domain, n_threads, subdomains):  | 
 | 27 | +    global q  | 
 | 28 | + | 
 | 29 | +    # fill the queue with all the subdomains  | 
 | 30 | +    for subdomain in subdomains:  | 
 | 31 | +        q.put(subdomain)  | 
 | 32 | + | 
 | 33 | +    for t in range(n_threads):  | 
 | 34 | +        # start all threads  | 
 | 35 | +        worker = Thread(target=scan_subdomains, args=(domain,))  | 
 | 36 | +        # daemon thread means a thread that will end when the main thread ends  | 
 | 37 | +        worker.daemon = True  | 
 | 38 | +        worker.start()  | 
 | 39 | + | 
 | 40 | +      | 
 | 41 | + | 
 | 42 | + | 
 | 43 | +def print_n_threads():  | 
 | 44 | +    while True:  | 
 | 45 | +        print("Number of alive threads:", active_count())  | 
 | 46 | +        time.sleep(10)  | 
 | 47 | + | 
 | 48 | + | 
 | 49 | +if __name__ == "__main__":  | 
 | 50 | +    import argparse  | 
 | 51 | +    parser = argparse.ArgumentParser(description="Faster Subdomain Scanner using Threads")  | 
 | 52 | +    parser.add_argument("domain", help="Domain to scan for subdomains without protocol (e.g without 'http://' or 'https://')")  | 
 | 53 | +    parser.add_argument("-l", "--wordlist", help="File that contains all subdomains to scan, line by line. Default is subdomains.txt",  | 
 | 54 | +                        default="subdomains.txt")  | 
 | 55 | +    parser.add_argument("-t", "--num-threads", help="Number of threads to use to scan the domain. Default is 10", default=10, type=int)  | 
 | 56 | +      | 
 | 57 | +    args = parser.parse_args()  | 
 | 58 | +    domain = args.domain  | 
 | 59 | +    wordlist = args.wordlist  | 
 | 60 | +    num_threads = args.num_threads  | 
 | 61 | + | 
 | 62 | +    # t = Thread(target=print_n_threads)  | 
 | 63 | +    # t.daemon = True  | 
 | 64 | +    # t.start()  | 
 | 65 | + | 
 | 66 | +    main(domain=domain, n_threads=num_threads, subdomains=open(wordlist).read().splitlines())  | 
 | 67 | +    q.join()  | 
 | 68 | +      | 
0 commit comments