From 561741c086ba4ba5e23a32ce6b157a4c0ffabc66 Mon Sep 17 00:00:00 2001 From: Branch Vincent Date: Sat, 6 Apr 2024 11:33:17 -0700 Subject: [PATCH 1/2] migrate to pyproject.toml --- .github/workflows/DNSrecon.yml | 2 +- .gitignore | 5 ++- dnsrecon/cli.py | 5 ++- namelist.txt => dnsrecon/data/namelist.txt | 0 snoop.txt => dnsrecon/data/snoop.txt | 0 .../data/subdomains-top1mil-20000.txt | 0 .../data/subdomains-top1mil-5000.txt | 0 .../data/subdomains-top1mil.txt | 0 pyproject.toml | 38 ++++++++++++++++- requirements-dev.txt | 1 - setup.py | 41 ------------------- 11 files changed, 45 insertions(+), 47 deletions(-) rename namelist.txt => dnsrecon/data/namelist.txt (100%) rename snoop.txt => dnsrecon/data/snoop.txt (100%) rename subdomains-top1mil-20000.txt => dnsrecon/data/subdomains-top1mil-20000.txt (100%) rename subdomains-top1mil-5000.txt => dnsrecon/data/subdomains-top1mil-5000.txt (100%) rename subdomains-top1mil.txt => dnsrecon/data/subdomains-top1mil.txt (100%) delete mode 100644 setup.py diff --git a/.github/workflows/DNSrecon.yml b/.github/workflows/DNSrecon.yml index 038d6bc4..3effcb30 100644 --- a/.github/workflows/DNSrecon.yml +++ b/.github/workflows/DNSrecon.yml @@ -26,7 +26,7 @@ jobs: - name: Install dependencies run: | pip install --upgrade pip - pip install -r requirements-dev.txt + pip install .[dev] - name: Lint with ruff run: | diff --git a/.gitignore b/.gitignore index 41652be4..ac6e8da0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ *.pyc *.pyo venv/ -*.pytest_cache/ \ No newline at end of file +*.pytest_cache/ +*.egg-info +build/ +dist/ diff --git a/dnsrecon/cli.py b/dnsrecon/cli.py index 67281526..b9ae1fea 100755 --- a/dnsrecon/cli.py +++ b/dnsrecon/cli.py @@ -31,6 +31,7 @@ import sqlite3 from argparse import ArgumentParser, RawTextHelpFormatter from concurrent import futures +from pathlib import Path from random import SystemRandom from string import ascii_letters, digits from xml.dom import minidom @@ -60,6 +61,7 @@ brtdata = [] CONFIG = {'disable_check_recursion': False, 'disable_check_bindversion': False} +DATA_DIR = Path(__file__).parent / 'data' def process_range(arg): @@ -1810,8 +1812,7 @@ def main(): dictionary = '' if any(dictionary_required): # we generate a list of possible dictionary files - script_dir = os.path.dirname(os.path.realpath(__file__)) + os.sep - dictionaries = ['/etc/dnsrecon/namelist.txt', script_dir + 'namelist.txt'] + dictionaries = ['/etc/dnsrecon/namelist.txt', DATA_DIR / 'namelist.txt'] # if the user has provided a custom dictionary file, # we insert it as the first entry of the list diff --git a/namelist.txt b/dnsrecon/data/namelist.txt similarity index 100% rename from namelist.txt rename to dnsrecon/data/namelist.txt diff --git a/snoop.txt b/dnsrecon/data/snoop.txt similarity index 100% rename from snoop.txt rename to dnsrecon/data/snoop.txt diff --git a/subdomains-top1mil-20000.txt b/dnsrecon/data/subdomains-top1mil-20000.txt similarity index 100% rename from subdomains-top1mil-20000.txt rename to dnsrecon/data/subdomains-top1mil-20000.txt diff --git a/subdomains-top1mil-5000.txt b/dnsrecon/data/subdomains-top1mil-5000.txt similarity index 100% rename from subdomains-top1mil-5000.txt rename to dnsrecon/data/subdomains-top1mil-5000.txt diff --git a/subdomains-top1mil.txt b/dnsrecon/data/subdomains-top1mil.txt similarity index 100% rename from subdomains-top1mil.txt rename to dnsrecon/data/subdomains-top1mil.txt diff --git a/pyproject.toml b/pyproject.toml index bfbdf898..80826dc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,39 @@ +[project] +name = "dnsrecon" +description = "DNS Enumeration Script" +readme = "README.md" +authors = [{ name = "Carlos Perez", email = "carlos_perez@darkoperator.com" }] +requires-python = ">=3.9" +urls.Homepage = "https://github.com/darkoperator/dnsrecon" +classifiers = [ + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", + "Operating System :: OS Independent", +] +dynamic = ["dependencies", "optional-dependencies", "version"] + +[project.scripts] +dnsrecon = "dnsrecon.__main__:main" + +[tool.setuptools.dynamic] +version = { attr = "dnsrecon.cli.__version__" } +dependencies = { file = "requirements.txt" } +optional-dependencies.dev = { file = "requirements-dev.txt" } + +[tool.setuptools.packages.find] +include = ["dnsrecon*"] + +[tool.setuptools.package-data] +"*" = ["*.txt"] + +[build-system] +requires = ["setuptools>=68"] +build-backend = "setuptools.build_meta" + [tool.pytest.ini_options] minversion = "8.0.0" addopts = "--no-header" @@ -54,4 +90,4 @@ indent-style = "space" skip-magic-trailing-comma = false # Like Black, automatically detect the appropriate line ending. -line-ending = "auto" \ No newline at end of file +line-ending = "auto" diff --git a/requirements-dev.txt b/requirements-dev.txt index c5ecc7a2..17703505 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,2 @@ --r requirements.txt pytest==8.1.1 ruff==0.3.5 diff --git a/setup.py b/setup.py deleted file mode 100644 index 58c08c2f..00000000 --- a/setup.py +++ /dev/null @@ -1,41 +0,0 @@ -import setuptools - -from dnsrecon.cli import __version__ as dnsrecon_version - -with open('README.md') as fh: - long_description = fh.read() - -setuptools.setup( - name='dnsrecon', - version=dnsrecon_version, - author='Carlos Perez', - author_email='carlos_perez@darkoperator.com', - description='DNS Enumeration Script', - long_description=long_description, - long_description_content_type='text/markdown', - url='https://github.com/darkoperator/dnsrecon', - packages=setuptools.find_packages(exclude=['tests']), - python_requires='>=3.9', - entry_points={'console_scripts': ['dnsrecon = dnsrecon.__main__:main']}, - classifiers=[ - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.12', - 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', - 'Operating System :: OS Independent', - ], - data_files=[ - ( - '/etc/dnsrecon', - [ - 'namelist.txt', - 'snoop.txt', - 'subdomains-top1mil-20000.txt', - 'subdomains-top1mil-5000.txt', - 'subdomains-top1mil.txt', - ], - ) - ], -) From 524ff4d4817ec1ded2f595d9d346955fcc3331f5 Mon Sep 17 00:00:00 2001 From: Branch Vincent Date: Sat, 6 Apr 2024 11:47:07 -0700 Subject: [PATCH 2/2] fix formatting, dockerfile --- Dockerfile | 7 ++-- dnsrecon/cli.py | 99 +++++++++++++++++++++++-------------------------- 2 files changed, 50 insertions(+), 56 deletions(-) diff --git a/Dockerfile b/Dockerfile index ee829d3d..91c5b496 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,8 @@ -FROM python:alpine3 +FROM python:alpine WORKDIR /app COPY . /app RUN apk add --no-cache build-base libffi-dev libxml2-dev libxslt-dev RUN /usr/local/bin/python -m pip install --upgrade pip RUN /usr/local/bin/python --version -RUN pip3 install --no-cache-dir -r requirements.txt -RUN chmod +x *.py -ENTRYPOINT ["/app/dnsrecon.py"] +RUN pip3 install --no-cache-dir . +ENTRYPOINT ["dnsrecon"] diff --git a/dnsrecon/cli.py b/dnsrecon/cli.py index b9ae1fea..51551dc1 100755 --- a/dnsrecon/cli.py +++ b/dnsrecon/cli.py @@ -209,12 +209,12 @@ def check_nxdomain_hijack(nameserver): try: answers = res.resolve(testname, record_type, tcp=True) except ( - dns.resolver.NoNameservers, - dns.resolver.NXDOMAIN, - dns.exception.Timeout, - dns.resolver.NoAnswer, - socket.error, - dns.query.BadResponse, + dns.resolver.NoNameservers, + dns.resolver.NXDOMAIN, + dns.exception.Timeout, + dns.resolver.NoAnswer, + socket.error, + dns.query.BadResponse, ): continue @@ -287,8 +287,7 @@ def brute_tlds(res, domain, verbose=False, thread_num=None): future_results = { **{executor.submit(res.get_ip, f'{domain_main}.{tld}'): tld for tld in total_tlds}, **{executor.submit(res.get_ip, f'{domain_main}.{cc}'): cc for cc in cctld}, - **{executor.submit(res.get_ip, f'{domain_main}.{cc}.{tld}'): (cc, tld) for (cc, tld) in - zip(cctld, total_tlds)}, + **{executor.submit(res.get_ip, f'{domain_main}.{cc}.{tld}'): (cc, tld) for (cc, tld) in zip(cctld, total_tlds)}, } # Display logs as soon as a thread is finished @@ -435,7 +434,7 @@ def brute_reverse(res, ip_list, verbose=False, thread_num=None): ip_range = range(len(ip_list[i]) - 1) ip_group_size = 255 - for ip_group in [ip_range[j: j + ip_group_size] for j in range(0, len(ip_range), ip_group_size)]: + for ip_group in [ip_range[j : j + ip_group_size] for j in range(0, len(ip_range), ip_group_size)]: try: if verbose: for x in ip_group: @@ -459,13 +458,13 @@ def brute_reverse(res, ip_list, verbose=False, thread_num=None): def brute_domain( - res, - dictfile, - dom, - filter_=None, - verbose=False, - ignore_wildcard=False, - thread_num=None, + res, + dictfile, + dom, + filter_=None, + verbose=False, + ignore_wildcard=False, + thread_num=None, ): """ Main Function for domain brute forcing @@ -662,8 +661,7 @@ def whois_ips(res, ip_list): if 'a' in answer: for i in range(len(list_whois)): - print_status( - 'Performing Reverse Lookup of range {0}-{1}'.format(list_whois[i]['start'], list_whois[i]['end'])) + print_status('Performing Reverse Lookup of range {0}-{1}'.format(list_whois[i]['start'], list_whois[i]['end'])) found_records.append(brute_reverse(res, expand_range(list_whois[i]['start'], list_whois[i]['end']))) elif 'n' in answer: @@ -672,8 +670,7 @@ def whois_ips(res, ip_list): for a in answer: net_selected = list_whois[int(a)] print_status(net_selected['orgname']) - print_status( - 'Performing Reverse Lookup of range {0}-{1}'.format(net_selected['start'], net_selected['end'])) + print_status('Performing Reverse Lookup of range {0}-{1}'.format(net_selected['start'], net_selected['end'])) found_records.append(brute_reverse(res, expand_range(net_selected['start'], net_selected['end']))) else: print_error('No IP Ranges were found in the Whois query results') @@ -845,26 +842,26 @@ def write_db(db, data): for n in data: if re.match(r'PTR|^[A]$|AAAA', n['type']): query = ( - 'insert into data( domain, type, name, address ) ' - + 'values( "{domain}", "{type}", "{name}","{address}" )'.format(**n) + 'insert into data( domain, type, name, address ) ' + + 'values( "{domain}", "{type}", "{name}","{address}" )'.format(**n) ) elif re.match(r'NS$', n['type']): query = ( - 'insert into data( domain, type, name, address ) ' - + 'values( "{domain}", "{type}", "{target}", "{address}" )'.format(**n) + 'insert into data( domain, type, name, address ) ' + + 'values( "{domain}", "{type}", "{target}", "{address}" )'.format(**n) ) elif re.match(r'SOA', n['type']): query = ( - 'insert into data( domain, type, name, address ) ' - + 'values( "{domain}", "{type}", "{mname}", "{address}" )'.format(**n) + 'insert into data( domain, type, name, address ) ' + + 'values( "{domain}", "{type}", "{mname}", "{address}" )'.format(**n) ) elif re.match(r'MX', n['type']): query = ( - 'insert into data( domain, type, name, address ) ' - + 'values( "{domain}", "{type}", "{exchange}", "{address}" )'.format(**n) + 'insert into data( domain, type, name, address ) ' + + 'values( "{domain}", "{type}", "{exchange}", "{address}" )'.format(**n) ) elif re.match(r'TXT', n['type']): @@ -875,14 +872,14 @@ def write_db(db, data): elif re.match(r'SRV', n['type']): query = ( - 'insert into data( domain, type, name, target, address, port ) ' - + 'values( "{domain}", "{type}", "{name}" , "{target}", "{address}" ,"{port}" )'.format(**n) + 'insert into data( domain, type, name, target, address, port ) ' + + 'values( "{domain}", "{type}", "{name}" , "{target}", "{address}" ,"{port}" )'.format(**n) ) elif re.match(r'CNAME', n['type']): query = ( - 'insert into data( domain, type, name, target ) ' - + 'values( "{domain}", "{type}", "{name}" , "{target}" )'.format(**n) + 'insert into data( domain, type, name, target ) ' + + 'values( "{domain}", "{type}", "{name}" , "{target}" )'.format(**n) ) else: @@ -891,8 +888,7 @@ def write_db(db, data): del n['type'] record_data = ''.join([f'{key}={value},' for key, value in n.items()]) records = [t, record_data] - query = 'insert into data(domain,type,text) values ("%(domain)", \'' + records[0] + "','" + records[ - 1] + "')" + query = 'insert into data(domain,type,text) values ("%(domain)", \'' + records[0] + "','" + records[1] + "')" # Execute Query and commit cur.execute(query) @@ -937,8 +933,7 @@ def dns_sec_check(domain, res): except dns.exception.Timeout: print_error('A timeout error occurred please make sure you can reach the target DNS Servers') - print_error( - f'directly and requests are not being filtered. Increase the timeout from {res._res.timeout} second') + print_error(f'directly and requests are not being filtered. Increase the timeout from {res._res.timeout} second') print_error('to a higher number with --lifetime