diff --git a/Dockerfile b/Dockerfile index c0f1769..a8b4fd0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ ENV PATH=${PATH}:/Sublist3r2 RUN apt-get update && \ apt-get install -y build-essential libffi-dev libgit2-dev && \ - pip install -r /Sublist3r2/requirements.txt && \ + pip install /Sublist3r2 && \ addgroup Sublist3r2 --force-badname && \ useradd -g Sublist3r2 -d /Sublist3r2 -s /bin/sh Sublist3r2 && \ chown -R Sublist3r2:Sublist3r2 /Sublist3r2 && \ @@ -24,6 +24,6 @@ RUN apt-get update && \ USER Sublist3r2 -ENTRYPOINT ["sublist3r2.py"] +ENTRYPOINT ["sublist3r2"] CMD ["-h"] diff --git a/MANIFEST.in b/MANIFEST.in index 6feedd3..90bd747 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,2 @@ include LICENSE README.md -include aiodnsbrute/*.txt +include sublist3r2/aiodnsbrute/*.txt diff --git a/requirements.txt b/requirements.txt index f765236..b43d9c9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,8 @@ argparse dnspython requests -aiodnsbrute +asyncio +uvloop +tqdm +aiodns +click \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..038fea0 --- /dev/null +++ b/setup.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +import os +from setuptools import setup, find_packages + + +def read(fname: str) -> str: + """Open files relative to package.""" + return open(os.path.join(os.path.dirname(__file__), fname)).read() + + +setup( + name='sublist3r2', + version='1.0.1', + python_requires='>=3.6', + description='Subdomains enumeration tool for penetration testers', + long_description=read('README.md'), + long_description_content_type='text/markdown', + keywords='subdomain dns detection', + url='https://github.com/RoninNakomoto/Sublist3r2', + license='GPL-2.0', + packages=find_packages(), + include_package_data=True, + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Console', + 'Intended Audience :: Information Technology', + 'Intended Audience :: System Administrators', + 'Intended Audience :: Telecommunications Industry', + 'License :: OSI Approved :: GNU General Public License v2', + 'Operating System :: POSIX :: Linux', + 'Operating System :: MacOS', + 'Programming Language :: Python :: 3', + 'Topic :: Security', + ], + install_requires=[ + 'argparse', + 'dnspython', + 'requests', + 'asyncio', + 'uvloop', + 'tqdm', + 'aiodns', + 'click', + ], + entry_points={ + 'console_scripts': [ + 'sublist3r2 = sublist3r2:interactive', + ], + }, +) diff --git a/sublist3r2.py b/sublist3r2/__init__.py similarity index 85% rename from sublist3r2.py rename to sublist3r2/__init__.py index f66517f..9ce1e32 100755 --- a/sublist3r2.py +++ b/sublist3r2/__init__.py @@ -2,41 +2,28 @@ # coding: utf-8 # Sublist3r2 v1.0 - -# modules in standard library -import re -import sys -import os +# Builtin modules import argparse -import time import hashlib -import random -import multiprocessing -import threading -import socket import json +import multiprocessing +import os +import random +import re +import socket +import sys +import threading +import time +import urllib.parse as urlparse from collections import Counter -# external modules +# External modules import dns.resolver import requests -from aiodnsbrute.cli import aioDNSBrute +from sublist3r2.aiodnsbrute.cli import aioDNSBrute -# Python 2.x and 3.x compatiablity -if sys.version > '3': - import urllib.parse as urlparse - import urllib.parse as urllib -else: - import urlparse - import urllib - -# In case you cannot install some of the required development packages -# there's also an option to disable the SSL warning: -try: - import requests.packages.urllib3 - requests.packages.urllib3.disable_warnings() -except: - pass +# Version info +__version__ = '1.0.1' # Check if we are running this on windows platform is_windows = sys.platform.startswith('win') @@ -50,15 +37,14 @@ if is_windows: R = '\033[91m' # red W = '\033[0m' # white try: - import win_unicode_console , colorama + import colorama + import win_unicode_console win_unicode_console.enable() colorama.init() - #Now the unicode will work ^_^ - except: + # Now the unicode will work ^_^ + except Exception: print("[!] Error: Coloring libraries not installed, no coloring will be used [Check the readme]") - G = Y = B = R = W = G = Y = B = R = W = '' - - + G = Y = B = R = W = '' else: G = '\033[92m' # green Y = '\033[93m' # yellow @@ -66,6 +52,7 @@ else: R = '\033[91m' # red W = '\033[0m' # white + def no_color(): global G, Y, B, R, W G = Y = B = R = W = '' @@ -73,13 +60,13 @@ def no_color(): def banner(): print("""%s - ____ _ _ _ _ _____ _ ____ - / ___| _ _| |__ | (_)___| |_|___ / _ __\ __ | Sublist3r2 v1.0 + ____ _ _ _ _ _____ ______ + / ___| _ _| |__ | (_)___| |_|___ / _ __\ __ | Sublist3r2 v%s \___ \| | | | '_ \| | / __| __| |_ \| '__| / / a subdomains enum tool originally by @aboul3la ___) | |_| | |_) | | \__ \ |_ ___) | | / /_ maintained by Ronin Nakomoto - |____/ \__,_|_.__/|_|_|___/\__|____/|_| /____|%s%s https://github.com/RoninNakomoto/Sublist3r2 + |____/ \__,_|_.__/|_|_|___/\__|____/|_| /____|%s https://github.com/RoninNakomoto/Sublist3r2 - """ % (R, W, Y)) + """ % (R, __version__, Y)) # noqa def parser_error(errmsg): @@ -258,7 +245,10 @@ class enumratorBase(object): class enumratorBaseThreaded(multiprocessing.Process, enumratorBase): def __init__(self, base_url, engine_name, domain, subdomains=None, q=None, silent=False, verbose=True): subdomains = subdomains or [] - enumratorBase.__init__(self, base_url, engine_name, domain, subdomains, silent=silent, verbose=verbose) + enumratorBase.__init__( + self, base_url, engine_name, domain, subdomains, + silent=silent, verbose=verbose + ) multiprocessing.Process.__init__(self) self.q = q return @@ -276,13 +266,16 @@ class GoogleEnum(enumratorBaseThreaded): self.engine_name = "Google" self.MAX_DOMAINS = 11 self.MAX_PAGES = 200 - super(GoogleEnum, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose) + super(GoogleEnum, self).__init__( + base_url, self.engine_name, domain, subdomains, + q=q, silent=silent, verbose=verbose + ) self.q = q return def extract_domains(self, resp): links_list = list() - link_regx = re.compile('(.*?)<\/cite>') + link_regx = re.compile(r'(.*?)<\/cite>') try: links_list = link_regx.findall(resp) for link in links_list: @@ -299,7 +292,7 @@ class GoogleEnum(enumratorBaseThreaded): return links_list def check_response_errors(self, resp): - if (type(resp) is str or type(resp) is unicode) and 'Our systems have detected unusual traffic' in resp: + if (type(resp) is str) and 'Our systems have detected unusual traffic' in resp: self.print_(R + "[!] Error: Google probably now is blocking our requests" + W) self.print_(R + "[~] Finished now the Google Enumeration ..." + W) return False @@ -326,20 +319,23 @@ class YahooEnum(enumratorBaseThreaded): self.engine_name = "Yahoo" self.MAX_DOMAINS = 10 self.MAX_PAGES = 0 - super(YahooEnum, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose) + super(YahooEnum, self).__init__( + base_url, self.engine_name, domain, subdomains, + q=q, silent=silent, verbose=verbose + ) self.q = q return def extract_domains(self, resp): - link_regx2 = re.compile('(.*?)') - link_regx = re.compile('(.*?)') + link_regx2 = re.compile(r'(.*?)') + link_regx = re.compile(r'(.*?)') links_list = [] try: links = link_regx.findall(resp) links2 = link_regx2.findall(resp) links_list = links + links2 for link in links_list: - link = re.sub("<(\/)?b>", "", link) + link = re.sub(r'<(\/)?b>', '', link) if not link.startswith('http'): link = "http://" + link subdomain = urlparse.urlparse(link).netloc @@ -377,13 +373,16 @@ class AskEnum(enumratorBaseThreaded): self.engine_name = "Ask" self.MAX_DOMAINS = 11 self.MAX_PAGES = 0 - enumratorBaseThreaded.__init__(self, base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose) + enumratorBaseThreaded.__init__( + self, base_url, self.engine_name, domain, subdomains, + q=q, silent=silent, verbose=verbose + ) self.q = q return def extract_domains(self, resp): links_list = list() - link_regx = re.compile('

(.*?)

') + link_regx = re.compile(r'

(.*?)

') try: links_list = link_regx.findall(resp) for link in links_list: @@ -420,22 +419,25 @@ class BingEnum(enumratorBaseThreaded): self.engine_name = "Bing" self.MAX_DOMAINS = 30 self.MAX_PAGES = 0 - enumratorBaseThreaded.__init__(self, base_url, self.engine_name, domain, subdomains, q=q, silent=silent) + enumratorBaseThreaded.__init__( + self, base_url, self.engine_name, domain, subdomains, + q=q, silent=silent + ) self.q = q self.verbose = verbose return def extract_domains(self, resp): links_list = list() - link_regx = re.compile('
  • ||<|>', '', link) + link = re.sub(r'<(\/)?strong>||<|>', '', link) if not link.startswith('http'): link = "http://" + link subdomain = urlparse.urlparse(link).netloc @@ -465,7 +467,10 @@ class BaiduEnum(enumratorBaseThreaded): self.engine_name = "Baidu" self.MAX_DOMAINS = 2 self.MAX_PAGES = 760 - enumratorBaseThreaded.__init__(self, base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose) + enumratorBaseThreaded.__init__( + self, base_url, self.engine_name, domain, subdomains, + q=q, silent=silent, verbose=verbose + ) self.querydomain = self.domain self.q = q return @@ -474,11 +479,11 @@ class BaiduEnum(enumratorBaseThreaded): links = list() found_newdomain = False subdomain_list = [] - link_regx = re.compile('(.*?)') + link_regx = re.compile(r'(.*?)') try: links = link_regx.findall(resp) for link in links: - link = re.sub('<.*?>|>|<| ', '', link) + link = re.sub(r'<.*?>|>|<| ', '', link) if not link.startswith('http'): link = "http://" + link subdomain = urlparse.urlparse(link).netloc @@ -523,7 +528,10 @@ class NetcraftEnum(enumratorBaseThreaded): subdomains = subdomains or [] self.base_url = 'https://searchdns.netcraft.com/?restriction=site+ends+with&host={domain}' self.engine_name = "Netcraft" - super(NetcraftEnum, self).__init__(self.base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose) + super(NetcraftEnum, self).__init__( + self.base_url, self.engine_name, domain, subdomains, + q=q, silent=silent, verbose=verbose + ) self.q = q return @@ -541,7 +549,7 @@ class NetcraftEnum(enumratorBaseThreaded): return def get_next(self, resp): - link_regx = re.compile('Next Page') + link_regx = re.compile(r'Next Page') link = link_regx.findall(resp) url = 'http://searchdns.netcraft.com' + link[0] return url @@ -551,7 +559,9 @@ class NetcraftEnum(enumratorBaseThreaded): cookies_list = cookie[0:cookie.find(';')].split("=") cookies[cookies_list[0]] = cookies_list[1] # hashlib.sha1 requires utf-8 encoded str - cookies['netcraft_js_verification_response'] = hashlib.sha1(urllib.unquote(cookies_list[1]).encode('utf-8')).hexdigest() + cookies['netcraft_js_verification_response'] = hashlib.sha1( + urlparse.unquote(cookies_list[1]).encode('utf-8') + ).hexdigest() return cookies def get_cookies(self, headers): @@ -577,7 +587,7 @@ class NetcraftEnum(enumratorBaseThreaded): def extract_domains(self, resp): links_list = list() - link_regx = re.compile('', re.S) + csrf_regex = re.compile(r'', re.S) token = csrf_regex.findall(resp)[0] return token.strip() @@ -654,8 +667,8 @@ class DNSdumpster(enumratorBaseThreaded): return self.live_subdomains def extract_domains(self, resp): - tbl_regex = re.compile('<\/a>Host Records.*?(.*?)', re.S) - link_regex = re.compile('(.*?)
    ', re.S) + tbl_regex = re.compile(r'
    <\/a>Host Records.*?(.*?)', re.S) + link_regex = re.compile(r'(.*?)
    ', re.S) links = [] try: results_tbl = tbl_regex.findall(resp)[0] @@ -677,24 +690,25 @@ class Virustotal(enumratorBaseThreaded): subdomains = subdomains or [] base_url = 'https://www.virustotal.com/api/v3/domains/{domain}/subdomains' self.engine_name = "Virustotal" - if os.getenv("VT_APIKEY") is None: - VT_APIKEY=input(B + "[+] Enter VirusTotal API key, press Enter for none: " + W) - VT_APIKEY=VT_APIKEY.strip() - if VT_APIKEY != "": - os.environ["VT_APIKEY"]=(VT_APIKEY) - else: - VT_APIKEY = os.getenv("VT_APIKEY") - os.environ["VT_APIKEY"]=(VT_APIKEY) - self.apikey = os.getenv('VT_APIKEY', None) + self.apikey = os.getenv("VT_APIKEY") + + if self.apikey is None: + vt_apikey = input(B + "[+] Enter VirusTotal API key, press Enter for none: " + W).strip() + if vt_apikey != "": + self.apikey = vt_apikey + self.q = q - super(Virustotal, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose) + super(Virustotal, self).__init__( + base_url, self.engine_name, domain, subdomains, + q=q, silent=silent, verbose=verbose + ) self.url = self.base_url.format(domain=self.domain) return # the main send_req need to be rewritten def send_req(self, url): try: - self.headers.update({'X-ApiKey':self.apikey}) + self.headers.update({'X-ApiKey': self.apikey}) resp = self.session.get(url, headers=self.headers, timeout=self.timeout) except Exception as e: self.print_(e) @@ -705,11 +719,10 @@ class Virustotal(enumratorBaseThreaded): def enumerate(self): if self.apikey: while self.url != '': - #try: resp = self.send_req(self.url) resp = json.loads(resp) if 'error' in resp: - self.print_(R + "Error Code: {}".format(resp['error']["code"]) +W) + self.print_(R + "Error Code: {}".format(resp['error']["code"]) + W) self.print_(R + "Virus Total Server Message: {}".format(resp['error']["message"]) + W) break if 'links' in resp and 'next' in resp['links']: @@ -719,8 +732,8 @@ class Virustotal(enumratorBaseThreaded): self.extract_domains(resp) else: self.print_(R + "[!] Error: VirusTotal API key environment variable not found. Skipping" + W) - self.print_(R + "[!] set VT_APIKEY to your virus total API key using: export VT_APIKEY=Your_VT_API_KEY_VALUE" + W) - self.print_(B + "[!] To get a VT APIKEY, register at https://www.virustotal.com/gui/join-us" +W) + self.print_(R + "[!] set VT_APIKEY to your virus total API key using: `export VT_APIKEY=Your_VT_API_KEY_VALUE`" + W) + self.print_(B + "[!] To get a VT APIKEY, register at https://www.virustotal.com/gui/join-us" + W) return self.subdomains def extract_domains(self, resp): @@ -745,7 +758,10 @@ class ThreatCrowd(enumratorBaseThreaded): base_url = 'https://www.threatcrowd.org/searchApi/v2/domain/report/?domain={domain}' self.engine_name = "ThreatCrowd" self.q = q - super(ThreatCrowd, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose) + super(ThreatCrowd, self).__init__( + base_url, self.engine_name, domain, subdomains, + q=q, silent=silent, verbose=verbose + ) return def req(self, url): @@ -783,7 +799,10 @@ class CrtSearch(enumratorBaseThreaded): base_url = 'https://crt.sh/?q=%25.{domain}' self.engine_name = "SSL Certificates" self.q = q - super(CrtSearch, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose) + super(CrtSearch, self).__init__( + base_url, self.engine_name, domain, subdomains, + q=q, silent=silent, verbose=verbose + ) return def req(self, url): @@ -802,7 +821,7 @@ class CrtSearch(enumratorBaseThreaded): return self.subdomains def extract_domains(self, resp): - link_regx = re.compile('(.*?)') + link_regx = re.compile(r'(.*?)') try: links = link_regx.findall(resp) for link in links: @@ -818,7 +837,7 @@ class CrtSearch(enumratorBaseThreaded): continue if '@' in subdomain: - subdomain = subdomain[subdomain.find('@')+1:] + subdomain = subdomain[subdomain.find('@') + 1:] if subdomain not in self.subdomains and subdomain != self.domain: if self.verbose: @@ -828,13 +847,17 @@ class CrtSearch(enumratorBaseThreaded): print(e) pass + class PassiveDNS(enumratorBaseThreaded): def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True): subdomains = subdomains or [] base_url = 'https://api.sublist3r.com/search.php?domain={domain}' self.engine_name = "PassiveDNS" self.q = q - super(PassiveDNS, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose) + super(PassiveDNS, self).__init__( + base_url, self.engine_name, domain, subdomains, + q=q, silent=silent, verbose=verbose + ) return def req(self, url): @@ -910,7 +933,7 @@ def main(domain, threads, savefile, ports, silent, verbose, enable_bruteforce, e enable_bruteforce = True # Validate domain - domain_check = re.compile("^(http|https)?[a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,}$") + domain_check = re.compile(r'^(http|https)?[a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,}$') if not domain_check.match(domain): if not silent: print(R + "Error: Please enter a valid domain" + W) @@ -927,18 +950,19 @@ def main(domain, threads, savefile, ports, silent, verbose, enable_bruteforce, e if verbose and not silent: print(Y + "[-] verbosity is enabled, will show the subdomains results in realtime" + W) - supported_engines = {'baidu': BaiduEnum, - 'yahoo': YahooEnum, - 'google': GoogleEnum, - 'bing': BingEnum, - 'ask': AskEnum, - 'netcraft': NetcraftEnum, - 'dnsdumpster': DNSdumpster, - 'virustotal': Virustotal, - 'threatcrowd': ThreatCrowd, - 'ssl': CrtSearch, - 'passivedns': PassiveDNS - } + supported_engines = { + 'baidu': BaiduEnum, + 'yahoo': YahooEnum, + 'google': GoogleEnum, + 'bing': BingEnum, + 'ask': AskEnum, + 'netcraft': NetcraftEnum, + 'dnsdumpster': DNSdumpster, + 'virustotal': Virustotal, + 'threatcrowd': ThreatCrowd, + 'ssl': CrtSearch, + 'passivedns': PassiveDNS + } chosenEnums = [] @@ -968,15 +992,16 @@ def main(domain, threads, savefile, ports, silent, verbose, enable_bruteforce, e if enable_bruteforce: if not silent: print(G + "[-] Starting bruteforce module now using aiodnsbrute.." + W) - record_type = False path_to_file = os.path.dirname(os.path.realpath(__file__)) subs = os.path.join(path_to_file, 'aiodnsbrute', 'subdomains-top1million-110000.txt') resolvers = os.path.join(path_to_file, 'aiodnsbrute', 'resolvers.txt') - wildcard=True - verify=True - query=True + wildcard = True + verify = True + query = True thread_count = threads - bruteforce_list = aioDNSBrute.bruteforce_domain(parsed_domain.netloc, resolvers, subs, wildcard, verify, search_list, thread_count, query) + bruteforce_list = aioDNSBrute.bruteforce_domain( + parsed_domain.netloc, resolvers, subs, wildcard, verify, thread_count, query + ) subdomains = search_list.union(bruteforce_list) if subdomains: @@ -1015,7 +1040,11 @@ def interactive(): if args.no_color: no_color() banner() - res = main(domain, threads, savefile, ports, silent=False, verbose=verbose, enable_bruteforce=enable_bruteforce, engines=engines) + main( + domain, threads, savefile, ports, + silent=False, verbose=verbose, enable_bruteforce=enable_bruteforce, engines=engines + ) + if __name__ == "__main__": interactive() diff --git a/aiodnsbrute/__init__.py b/sublist3r2/aiodnsbrute/__init__.py similarity index 100% rename from aiodnsbrute/__init__.py rename to sublist3r2/aiodnsbrute/__init__.py diff --git a/aiodnsbrute/cli.py b/sublist3r2/aiodnsbrute/cli.py similarity index 96% rename from aiodnsbrute/cli.py rename to sublist3r2/aiodnsbrute/cli.py index 0c4ecbc..2b7a9fd 100644 --- a/aiodnsbrute/cli.py +++ b/sublist3r2/aiodnsbrute/cli.py @@ -9,7 +9,7 @@ import click import socket import sys from tqdm import tqdm -from aiodnsbrute.logger import ConsoleLogger +from sublist3r2.aiodnsbrute.logger import ConsoleLogger class aioDNSBrute(object): @@ -74,7 +74,7 @@ class aioDNSBrute(object): if err_number == 4: # This is domain name not found, ignore it pass - # elif err_number == 12: + #elif err_number == 12: # Timeout from DNS server #self.logger.warn(f"Timeout for {name}") elif err_number == 1: @@ -118,7 +118,6 @@ class aioDNSBrute(object): self.tasks.remove(future) if self.verbosity >= 1: self.pbar.update() - async def _queue_lookups(self, wordlist, domain): """Takes a list of words and adds them to the async loop also passing the original @@ -137,19 +136,19 @@ class aioDNSBrute(object): self.tasks.append(task) await asyncio.gather(*self.tasks, return_exceptions=True) - def bruteforce_domain(target, resolvers=None, wordlist="subdomains-top1million-110000.txt", wildcard=True, verify=True, found_subdomains=[], thread_count=7000, query=True): + def bruteforce_domain(target, resolvers=None, wordlist="subdomains-top1million-110000.txt", wildcard=True, verify=True, thread_count=7000, query=True): subdomains_list = [] names_list = [] - verbosity=1 + verbosity = 1 if resolvers: - resolverfile = open(resolvers,'r') - lines = resolverfile.read().splitlines() - resolvers = [x.strip() for x in lines if (x and not x.startswith("#"))] + resolverfile = open(resolvers, 'r') + lines = resolverfile.read().splitlines() + resolvers = [x.strip() for x in lines if (x and not x.startswith("#"))] bf = aioDNSBrute(verbosity=verbosity, max_tasks=thread_count) subdomains_list = bf.run(wordlist, target, resolvers, wildcard, verify, query) resolverfile.close() for r in range(1, len(subdomains_list)): - names_list.append(subdomains_list[r]['domain']) + names_list.append(subdomains_list[r]['domain']) return names_list diff --git a/aiodnsbrute/logger.py b/sublist3r2/aiodnsbrute/logger.py similarity index 100% rename from aiodnsbrute/logger.py rename to sublist3r2/aiodnsbrute/logger.py diff --git a/aiodnsbrute/logger/logger.py b/sublist3r2/aiodnsbrute/logger/logger.py similarity index 100% rename from aiodnsbrute/logger/logger.py rename to sublist3r2/aiodnsbrute/logger/logger.py diff --git a/aiodnsbrute/resolvers.txt b/sublist3r2/aiodnsbrute/resolvers.txt similarity index 100% rename from aiodnsbrute/resolvers.txt rename to sublist3r2/aiodnsbrute/resolvers.txt diff --git a/aiodnsbrute/subdomains-top1million-110000.txt b/sublist3r2/aiodnsbrute/subdomains-top1million-110000.txt similarity index 100% rename from aiodnsbrute/subdomains-top1million-110000.txt rename to sublist3r2/aiodnsbrute/subdomains-top1million-110000.txt