#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# A simple and fast sub domains brute tool for pentesters
# my[at]lijiejie.com (http://www.lijiejie.com)

import Queue
import sys
import dns.resolver
import threading
import time
import optparse
import os
from lib.consle_width import getTerminalSize

class DNSBrute:
    def __init__(self, target, names_file, ignore_intranet, threads_num, output):
        self.target = target.strip()
        self.names_file = names_file
        self.ignore_intranet = ignore_intranet
        self.thread_count = self.threads_num = threads_num
        self.scan_count = self.found_count = 0
        self.lock = threading.Lock()
        self.console_width = getTerminalSize()[0] - 2    # Cal terminal width when starts up
        self.resolvers = [dns.resolver.Resolver() for _ in range(threads_num)]
        self._load_dns_servers()
        self._load_sub_names()
        self._load_next_sub()
        outfile = target + '.txt' if not output else output
        self.outfile = open(outfile, 'w')   # won't close manually
        self.ip_dict = {}
        self.STOP_ME = False

def _load_dns_servers(self):
        dns_servers = []
        with open('dict/dns_servers.txt') as f:
            for line in f:
                server = line.strip()
                if server.count('.') == 3 and server not in dns_servers:
                    dns_servers.append(server)
        self.dns_servers = dns_servers
        self.dns_count = len(dns_servers)

def _load_sub_names(self):
        self.queue = Queue.Queue()
        file = 'dict/' + self.names_file if not os.path.exists(self.names_file) else self.names_file
        with open(file) as f:
            for line in f:
                sub = line.strip()
                if sub: self.queue.put(sub)

def _load_next_sub(self):
        next_subs = []
        with open('dict/next_sub.txt') as f:
            for line in f:
                sub = line.strip()
                if sub and sub not in next_subs:
                    next_subs.append(sub)
        self.next_subs = next_subs

def _update_scan_count(self):
        self.lock.acquire()
        self.scan_count += 1
        self.lock.release()

def _print_progress(self):
        self.lock.acquire()
        msg = '%s found | %s remaining | %s scanned in %.2f 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()
        self.lock.release()

@staticmethod
    def is_intranet(ip):
        ret = ip.split('.')
        if not 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

def _scan(self):
        thread_id = int( threading.currentThread().getName() )
        self.resolvers[thread_id].nameservers.insert(0, self.dns_servers[thread_id % self.dns_count])
        self.resolvers[thread_id].lifetime = self.resolvers[thread_id].timeout = 10.0
        while self.queue.qsize() > 0 and not self.STOP_ME and self.found_count < 40000:    # limit max found records to 40000
            sub = self.queue.get(timeout=1.0)
            for _ in range(3):
                try:
                    cur_sub_domain = sub + '.' + self.target
                    answers = d.resolvers[thread_id].query(cur_sub_domain)
                    is_wildcard_record = False
                    if answers:
                        for answer in answers:
                            self.lock.acquire()
                            if answer.address not in self.ip_dict:
                                self.ip_dict[answer.address] = 1
                            else:
                                self.ip_dict[answer.address] += 1
                                if self.ip_dict[answer.address] > 2:    # a wildcard DNS record
                                    is_wildcard_record = True
                            self.lock.release()
                        if is_wildcard_record:
                            self._update_scan_count()
                            self._print_progress()
                            continue
                        ips = ', '.join([answer.address for answer in answers])
                        if (not self.ignore_intranet) or (not DNSBrute.is_intranet(answers[0].address)):
                            self.lock.acquire()
                            self.found_count += 1
                            msg = cur_sub_domain.ljust(30) + ips
                            sys.stdout.write('\r' + msg + ' ' * (self.console_width- len(msg)) + '\n\r')
                            sys.stdout.flush()
                            self.outfile.write(cur_sub_domain.ljust(30) + '\t' + ips + '\n')
                            self.lock.release()
                            try:
                                d.resolvers[thread_id].query('*.' + cur_sub_domain)
                            except:
                                for i in self.next_subs:
                                    self.queue.put(i + '.' + sub)
                        break
                except dns.resolver.NoNameservers, e:
                    break
                except Exception, e:
                    pass
            self._update_scan_count()
            self._print_progress()
        self._print_progress()
        self.lock.acquire()
        self.thread_count -= 1
        self.lock.release()

def run(self):
        self.start_time = time.time()
        for i in range(self.threads_num):
            t = threading.Thread(target=self._scan, name=str(i))
            t.setDaemon(True)
            t.start()
        while self.thread_count > 1:
            try:
                time.sleep(1.0)
            except KeyboardInterrupt,e:
                msg = '[WARNING] User aborted, wait all slave threads to exit...'
                sys.stdout.write('\r' + msg + ' ' * (self.console_width- len(msg)) + '\n\r')
                sys.stdout.flush()
                self.STOP_ME = True

if __name__ == '__main__':
    parser = optparse.OptionParser('usage: %prog [options] target.com')
    parser.add_option('-t', '--threads', dest='threads_num',
              default=60, type='int',
              help='Number of threads. default = 60')
    parser.add_option('-f', '--file', dest='names_file', default='dict/subnames.txt',
              type='string', help='Dict file used to brute sub names')
    parser.add_option('-i', '--ignore-intranet', dest='i', default=False, action='store_true',
              help='Ignore domains pointed to private IPs')
    parser.add_option('-o', '--output', dest='output', default=None,
              type='string', help='Output file name. default is {target}.txt')

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

d = DNSBrute(target=args[0], names_file=options.names_file,
                 ignore_intranet=options.i,
                 threads_num=options.threads_num,
                 output=options.output)
    d.run()
    while threading.activeCount() > 1:
        time.sleep(0.1)

摘自:李姐姐的博客

暴力枚举N级子域名的更多相关文章

  1. 51Nod 1158 全是1的最大子矩阵 —— 预处理 + 暴力枚举 or 单调栈

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1158 1158 全是1的最大子矩阵  基准时间限制:1 秒 空 ...

  2. [Unity3D]巧妙利用父级子级实现Camera场景平面漫游

    本文系作者原创,转载请注明出处 入门级的笔者想了一上午才搞懂那个欧拉角的Camera旋转..=.= 在调试场景的时候,每次都本能的按下W想前进,但是这是不可能的(呵呵) 于是便心血来潮想顺便添加个Ke ...

  3. CodeForces 742B Arpa’s obvious problem and Mehrdad’s terrible solution (暴力枚举)

    题意:求定 n 个数,求有多少对数满足,ai^bi = x. 析:暴力枚举就行,n的复杂度. 代码如下: #pragma comment(linker, "/STACK:1024000000 ...

  4. 2014牡丹江网络赛ZOJPretty Poem(暴力枚举)

    /* 将给定的一个字符串分解成ABABA 或者 ABABCAB的形式! 思路:暴力枚举A, B, C串! */ 1 #include<iostream> #include<cstri ...

  5. HNU 12886 Cracking the Safe(暴力枚举)

    题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12886&courseid=274 解题报告:输入4个数 ...

  6. 51nod 1116 K进制下的大数 (暴力枚举)

    题目链接 题意:中文题. 题解:暴力枚举. #include <iostream> #include <cstring> using namespace std; ; ; ch ...

  7. Windows下Apache服务器中自动配置二级子域名

    今天我们介绍的这个办法,只需要简单修改 httpd-vhosts.conf 文件,配合 .htaccess 文件即可实现自动配置二级域名. 我们这里以 wpchina.com 为例,以下代码中的 wp ...

  8. Codeforces Round #349 (Div. 1) B. World Tour 最短路+暴力枚举

    题目链接: http://www.codeforces.com/contest/666/problem/B 题意: 给你n个城市,m条单向边,求通过最短路径访问四个不同的点能获得的最大距离,答案输出一 ...

  9. bzoj 1028 暴力枚举判断

    昨天梦到这道题了,所以一定要A掉(其实梦到了3道,有两道记不清了) 暴力枚举等的是哪张牌,将是哪张牌,然后贪心的判断就行了. 对于一个状态判断是否为胡牌,1-n扫一遍,然后对于每个牌,先mod 3, ...

随机推荐

  1. Silicon Labs

    Silicon Labs(美国芯科实验室)总部位于美国德克萨斯州的奥斯汀,成立于1996年,拥有全球化的运营.销售和研发团队,是一家业界领先的高性能混合信号IC供应商,为业界提供易用的高度集成化产品方 ...

  2. 去掉windows8.1鸡肋的开始按钮

    无开始按钮了,win8.1的 开始按钮反而非常鸡肋.. 可以使用我分享的链接下载startisgone: http://download.csdn.net/detail/wangallan/89728 ...

  3. spring项目部署到resin4中的无法注入问题

    碰到个奇葩事啊,一个spring的项目拿到客户现场部署到resin4中,启动后各种报无法注入bean,找不到bean的问题.出现大量下图的错误: nested exception is org.spr ...

  4. linux 命令之grep

    grep主要用来在文件中进行正则查找 通常都会将高亮颜色打开,方便阅读,为grep建立一个别名alias放到.bashrc等文件中: alias grep='grep --color=auto' 最常 ...

  5. Entity Framework Code First反向生成代码

    那些年我们生成的代码 早年,笨点的方法通常都是使用DbFirst先生成cs,然后把CS复制出来做些修改 后台基本上就自己使用T4来写,但是一直也没时间完善成通用的版本 MS官方 提供了EntityFr ...

  6. 关于LogStash运行在AIX 64位机器上的问题与临时解决方案

    需求;logstash运行在SUSE,LINUX,PPC LINUX,AIX机器上,并监控文件发送日志到KAFKA中去, 问题:在AIX机器上,file插件总是报异常,无法完成数据的读取 NotImp ...

  7. 【转载】Serif和Sans-serif字体的区别

    在西方国家罗马字母阵营中,字体分为两大种类:Sans Serif和Serif,打字机体虽然也属于Sans Serif,但由于是等宽字体,所以另外独立出Monospace这一种类,例如在Web中,表示代 ...

  8. 浅显易懂的理解JavaScript中的this关键字

    在JavaScript中this变量是一个令人难以摸清的关键字,this可谓是非常强大,充分了解this的相关知识有助于我们在编写面向对象的JavaScript程序时能够游刃有余. 1. 一般用处 对 ...

  9. java并发编程学习: 阻塞队列 使用 及 实现原理

    队列(Queue)与栈(Stack)是数据结构中的二种常用结构,队列的特点是先进先出(First In First Out),而Stack是先进后出(First In Last Out),说得通俗点: ...

  10. docfx组件介绍--YamlSerialization

    在docfx中把元数据以yaml的形式保存,在metadata阶段会序列化数据到yaml文件中,在build阶段又需要从yaml文件反序列化出来.在使用过程中,意外发现yamldotnet在处理大量强 ...