1. 程式人生 > >子域名爆破

子域名爆破

main () encoding follow pty sage [] lob not

Preface

  Github傳送地址: findSubDomains

  這個腳本源自lijiejie/subDomainsBrute, 用來探測子域名,我刪除了很多代碼,也添加了不少註釋,使得代碼變得更簡練和清晰。

  你可以在這看到找到這個項目: https://github.com/lijiejie/subDomainsBrute

Dependencies

pip install dnspython gevent

Usage

python findSubDomains.py [your target domain]

Example

?  subDomainsBrute git:(master) ? python findSubDomains.py baidu.com
[
*] Validate DNS servers ... [+] Check DNS Server 223.6.6.6 < OK > Found 4 [*] Found 4 available DNS Servers in total [+] Load sub names ... [
+] Load sub names ... [*] Exploiting sub domains of baidu.com [+] There are 15372 subs waiting for trying ... -------------------------------------- [*] Initializing 100
threads 123.baidu.com 115.239.210.27, 115.239.211.112 0.baidu.com 180.149.144.203 1.baidu.com 61.135.186.115 11.baidu.com 220.181.57.55 12.baidu.com 220.181.57.166 100.baidu.com 180.149.131.33 1111.baidu.com 180.97.93.38 2013.baidu.com 180.149.131.33 2014.baidu.com 115.239.210.174, 180.97.33.136 365.baidu.com 180.149.131.33 3g.baidu.com 115.239.217.67, 115.239.217.68 7.baidu.com 61.135.185.212

代碼

鏈接

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
    @version : subDomainsBrute 1.0.6
    @author : lijiejie
    description : A simple and fast sub domains brute tool for pentesters
    @contact : my[at]lijiejie.com (http://www.lijiejie.com)
    Modified by : starnight_cyber
    @contact : [email protected]
    blog : http://www.cnblogs.com/Hi-blog/
    Time : 2017.09.23
"""

"""
    program description : subDomainsBrute is for finding sub domains of a target domain
    a very simple way turns to be brute force, simple and effective
    ~ and the idea is simple too, find the target sub domains using dictionary (important)
    ~ using the found sub domains for further brute force
    ~ before that, you have to know how the DNS works, please refer to concerned materials
"""

import gevent
from gevent import monkey
monkey.patch_all()
from gevent.pool import Pool
from gevent.queue import PriorityQueue
import sys
import re
import dns.resolver
import time
import optparse
import os
from lib.consle_width import getTerminalSize
from multiprocessing import cpu_count

class SubNameBrute:
    """
        receive commandline args and do some initialization work
    """
    def __init__(self, target, options):
        self.start_time = time.time()
        self.target = target.strip()
        self.options = options
        self.scan_count = self.found_count = 0
        self.console_width = getTerminalSize()[0] - 2

        # create dns resolver pool ~ workers
        self.resolvers = [dns.resolver.Resolver(configure=False) for _ in range(options.threads)]
        for resolver in self.resolvers:
            resolver.lifetime = resolver.timeout = 10.0

        self.print_count = 0
        self.STOP_ME = False

        # load dns servers and check whether these dns servers works fine ?
        self._load_dns_servers()

        # load sub names
        self.subs = []                          # subs in file
        self.goodsubs = []                      # checks ok for further exploitation
        self._load_subname(dict/subnames.txt, self.subs)

        # load sub.sub names
        self.subsubs = []
        self._load_subname(dict/next_sub.txt, self.subsubs)

        # results will be save to target.txt
        self.outfile = open(target + .txt, a)

        self.ip_dict = set()                            #
        self.found_sub = set()

        # task queue
        self.queue = PriorityQueue()
        for sub in self.subs:
            self.queue.put(sub)

    """
        Load DNS Servers(ip saved in file), and check whether the DNS servers works fine
    """
    def _load_dns_servers(self):

        print [*] Validate DNS servers ...
        self.dns_servers = []

        # create a process pool for checking DNS servers, the number is your processors(cores) * 4, just change it!
        processors = cpu_count() * 4
        pool = Pool(processors)

        # read dns ips and check one by one
        for server in open(dict/dns_servers.txt).xreadlines():
            server = server.strip()
            if server:
                pool.apply_async(self._test_server, (server, ))

        pool.join()                                     # waiting for process finish
        self.dns_count = len(self.dns_servers)

        sys.stdout.write(\n)
        print [*] Found %s available DNS Servers in total % self.dns_count
        if self.dns_count == 0:
            print [ERROR] No DNS Servers available.
            sys.exit(-1)

    """
        test these dns servers whether works fine
    """
    def _test_server(self, server):

        # create a dns resolver and set timeout
        resolver = dns.resolver.Resolver()
        resolver.lifetime = resolver.timeout = 10.0

        try:
            resolver.nameservers = [server]

            # test : resolving a known domain, and check whether can get the right result
            answers = resolver.query(public-dns-a.baidu.com)
            if answers[0].address != 180.76.76.76:
                raise Exception(incorrect DNS response)
            self.dns_servers.append(server)
        except:
            self._print_msg([-] Check DNS Server %s <Fail>   Found %s % (server.ljust(16), len(self.dns_servers)))

        self._print_msg([+] Check DNS Server %s < OK >   Found %s % (server.ljust(16), len(self.dns_servers)))

    """
        load sub names in dict/*.txt, one function would be enough
        file for read, subname_list for saving sub names
    """
    def _load_subname(self, file, subname_list):
        self._print_msg(‘[+] Load sub names ...‘)

        with open(file) as f:
            for line in f:
                sub = line.strip()
                if sub and sub not in subname_list:
                    tmp_set = {sub}

                    """
                        in case of the sub names which contains the following expression
                        and replace them {alphnum}, {alpha}, {num} with character and num
                    """
                    while len(tmp_set) > 0:
                        item = tmp_set.pop()
                        if item.find(‘{alphnum}‘) >= 0:
                            for _letter in ‘abcdefghijklmnopqrstuvwxyz0123456789‘:
                                tmp_set.add(item.replace(‘{alphnum}‘, _letter, 1))
                        elif item.find(‘{alpha}‘) >= 0:
                            for _letter in ‘abcdefghijklmnopqrstuvwxyz‘:
                                tmp_set.add(item.replace(‘{alpha}‘, _letter, 1))
                        elif item.find(‘{num}‘) >= 0:
                            for _letter in ‘0123456789‘:
                                tmp_set.add(item.replace(‘{num}‘, _letter, 1))
                        elif item not in subname_list:
                            subname_list.append(item)

    """
        for better presentation of brute force results, not really matters ...
    """
    def _print_msg(self, _msg=None, _found_msg=False):
        if _msg is None:
            self.print_count += 1
            if self.print_count < 100:
                return
            self.print_count = 0
            msg = ‘%s Found| %s Groups| %s scanned in %.1f seconds‘ % (
                self.found_count, self.queue.qsize(), self.scan_count, time.time() - self.start_time)
            sys.stdout.write(‘\r‘ + ‘ ‘ * (self.console_width - len(msg)) + msg)
        elif _msg.startswith(‘[+] Check DNS Server‘):
            sys.stdout.write(‘\r‘ + _msg + ‘ ‘ * (self.console_width - len(_msg)))
        else:
            sys.stdout.write(‘\r‘ + _msg + ‘ ‘ * (self.console_width - len(_msg)) + ‘\n‘)
            if _found_msg:
                msg = ‘%s Found| %s Groups| %s scanned in %.1f seconds‘ % (
                    self.found_count, self.queue.qsize(), self.scan_count, time.time() - self.start_time)
                sys.stdout.write(‘\r‘ + ‘ ‘ * (self.console_width - len(msg)) + msg)
        sys.stdout.flush()

    """
        important : assign task to resolvers
    """
    def _scan(self, j):
        self.resolvers[j].nameservers = [self.dns_servers[j % self.dns_count]]
        while not self.queue.empty():
            sub = self.queue.get(timeout=1.0)

            # print cur_sub_domain
            try:
                cur_sub_domain = sub + ‘.‘ + self.target
                answers = self.resolvers[j].query(cur_sub_domain)
            except:
                continue

            if answers:
                ips = ‘, ‘.join(sorted([answer.address for answer in answers]))

                # exclude : intranet or kept addresses
                if ips in [‘1.1.1.1‘, ‘127.0.0.1‘, ‘0.0.0.0‘]:
                    continue
                if SubNameBrute.is_intranet(answers[0].address):
                    continue

                self.found_sub.add(cur_sub_domain)
                for answer in answers:
                    self.ip_dict.add(answer.address)

                if sub not in self.goodsubs:
                    self.goodsubs.append(sub)

                print cur_sub_domain, ‘\t‘, ips
                self.outfile.write(cur_sub_domain + ‘\t‘ + ips + ‘\n‘)

    @staticmethod
    def is_intranet(ip):
        ret = ip.split(‘.‘)
        if len(ret) != 4:
            return True
        if ret[0] == ‘10‘:
            return True
        if ret[0] == ‘172‘ and 16 <= int(ret[1]) <= 32:
            return True
        if ret[0] == ‘192‘ and ret[1] == ‘168‘:
            return True
        return False

    """
        assign task to threads ...
    """
    def run(self):
        threads = [gevent.spawn(self._scan, i) for i in range(self.options.threads)]

        print ‘[*] Initializing %d threads‘ % self.options.threads

        try:
            gevent.joinall(threads)
        except KeyboardInterrupt, e:
            msg = ‘[WARNING] User aborted.‘
            sys.stdout.write(‘\r‘ + msg + ‘ ‘ * (self.console_width - len(msg)) + ‘\n\r‘)
            sys.stdout.flush()


if __name__ == ‘__main__‘:
    parser = optparse.OptionParser(‘usage: %prog [options] target.com‘, version="%prog 1.0.6")
    parser.add_option(‘-f‘, dest=‘file‘, default=‘subnames.txt‘,
                      help=‘File contains new line delimited subs, default is subnames.txt.‘)
    parser.add_option(‘--full‘, dest=‘full_scan‘, default=False, action=‘store_true‘,
                      help=‘Full scan, NAMES FILE subnames_full.txt will be used to brute‘)
    parser.add_option(‘-t‘, ‘--threads‘, dest=‘threads‘, default=100, type=int,
                      help=‘Num of scan threads, 100 by default‘)

    (options, args) = parser.parse_args()
    if len(args) < 1:
        parser.print_help()
        sys.exit(0)

    # initialization ...
    d = SubNameBrute(target=args[0], options=options)

    print ‘[*] Exploiting sub domains of ‘, args[0]
    print ‘[+] There are %d subs waiting for trying ...‘ % len(d.queue)
    print ‘--------------------------------------‘
    d.run()
    print ‘--------------------------------------‘
    print ‘%d subnames found‘ % len(d.found_sub)
    print ‘[*] Program running %.1f seconds ‘ % (time.time() - d.start_time)

    print ‘[*] It is usually not recommended to exploit second-level sub domains,because needs to try %d times‘           % (len(d.subsubs) * len(d.goodsubs))
    go_on = raw_input(‘[-] Are you consist? YES/NO : ‘)
    if go_on == ‘YES‘ or go_on == ‘y‘ or go_on == ‘Y‘ or go_on == ‘yes‘:
        print ‘[*]Exploiting second level sub names ...‘

        d.queue = PriorityQueue()
        for subsub in d.subsubs:
            for sub in d.goodsubs:
                subname = subsub + ‘.‘ + sub
                d.queue.put(subname)

        print ‘There are %d subs waiting for trying ...‘ % len(d.queue)
        d.run()
    else:
        pass

    print ‘%d subnames found in total‘ % len(d.found_sub)
    print ‘[*]Results are saved to threes files starts with %s‘ % args

    """
        save ips and domains to files
    """
    with open(args[0]+‘-ip.txt‘, ‘w‘) as f:
        for ip in d.ip_dict:
            f.write(ip + ‘\n‘)

    with open(args[0] + ‘-subdomain.txt‘, ‘w‘) as f:
        for domain in d.found_sub:
            f.write(domain + ‘\n‘)

    print ‘[*] Program running %.1f seconds ‘ % (time.time() - d.start_time)

    d.outfile.flush()
    d.outfile.close()

需要提供兩個子域名字典,就不提供百度雲下載鏈接了,具體請參看Github findSubDomains

不斷完善中,希望能收到您的意見 ~ RFC。

子域名爆破