子域名爆破

Preface

Github传送地址: findSubDomains 

现采用python3,实现更简洁,请直接参考github地址。

  这个脚本源自lijiejie/subDomainsBrute, 用来探测子域名,我删除了很多代码,也添加了不少注释,使得代码变得更简练和清晰。

  你可以在这看到找到这个项目subDomainsBrute: https://github.com/lijiejie/subDomainsBrute

关于子域名采集,还有一些不错的项目可以参考:

  knock : https://github.com/guelfoweb/knock
  Layer子域名挖掘机 : http://www.cnseay.com/4482/

  wydomain : https://github.com/ring04h/wydomain 

  dnsmaper : https://github.com/le4f/dnsmaper  [可以看到生成的地图,速度略慢]

还有两个比较受欢迎的,不过我用的时候不是卡死就是慢,可以尝试一下:

  Sublist3r : https://github.com/starnightcyber/Sublist3r

  Fierce : https://github.com/davidpepper/fierce-domain-scanner 

下面是关于本项目findSubDomains的一些相关说明:

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 : starnight_cyber@foxmail.com
    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

转载于:https://www.cnblogs.com/Hi-blog/p/7606027.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值