pdknockr

- Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.acid.vegas/-c.git
Log | Files | Refs | Archive | README

commit 70acaaacd63e12b52a77f780377775b91847fc23
Author: acidvegas <acid.vegas@acid.vegas>
Date: Sat, 25 Nov 2023 15:28:32 -0500

Inital commit

Diffstat:
AREADME.md | 9+++++++++
Apdknockr.py | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2 files changed, 103 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md
@@ -0,0 +1,8 @@
+# pdKnockr
+> A passive DNS "dive-by" tool
+
+This tool is designed to detect passive DNS servers that are logging DNS queries by performing targeted subdomain lookups on a list of specified DNS resolvers. The core functionality of the program lies in its ability to generate unique subdomains using a seed value, ensuring that each query is distinct and traceable. This approach is particularly effective in identifying passive DNS servers, which typically log and store DNS queries for analysis and tracking purposes. By generating these unique queries, the tool can pinpoint which DNS resolvers are passively logging requests, a critical insight for network security analysis and privacy assessments.
+
+The program operates by accepting a list of DNS resolver addresses and a seed value for subdomain generation. It then asynchronously queries each resolver with a dynamically generated subdomain, based on the provided seed, targeting a specific domain. The asynchronous nature of the tool allows for high-throughput and efficient querying, making it suitable for scanning a large number of resolvers in a short period. Users should note that while this tool provides valuable insights into DNS logging practices, it should be used responsibly and in compliance with applicable network and privacy regulations. It serves as a powerful instrument for network administrators, security researchers, and privacy advocates to understand and evaluate the extent of passive DNS logging in their networks or across various resolvers.
+
+## WORK IN PROGRESS (STAY TUNED)
+\ No newline at end of file
diff --git a/pdknockr.py b/pdknockr.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# Passive DNS Knocker (PDK) - developed by acidvegas in python (https://git.acid.vegas/pdknockr)
+
+import asyncio
+import random
+
+try:
+    import aiodns
+except ImportError:
+    raise SystemExit('missing required \'aiodns\' module (pip install aiodns)')
+
+
+async def dns_lookup(domain: str, subdomain: str, dns_server: str):
+    '''
+    Perform a DNS lookup on a target domain.
+    
+    :param domain: The target domain to perform the lookup on.
+    :param subdomain: The subdomain to look up.
+    :param dns_server: The DNS server to perform the lookup on.
+    '''
+    domain = f'{subdomain}.{domain}'
+    resolver = aiodns.DNSResolver(nameservers=[dns_server])
+    try:
+        answers = await resolver.query(domain, 'A')
+        print(f'[\033[92mDONE\033[0m] Knocking \033[96m{domain}\033[0m on \033[93m{dns_server}\033[0m')
+    except Exception as e:
+        print(f'Error resolving {domain} using {dns_server}: {e}')
+
+
+async def main(input_file: str, domains: str, subdomain: str, concurrency: int):
+    '''
+    Main function for the program.
+    
+    :param input_file: The file containing the list of domains to perform lookups on.
+    :param domains: The comma seperated list of domains to perform lookups on.
+    :param subdomain: The subdomain to look up.
+    :param concurrency: The maximum number of concurrent lookups to perform.
+    '''
+    semaphore = asyncio.BoundedSemaphore(concurrency)
+
+    if args.domains:
+        domains = args.domains.split(',')
+        async for domain in domains:
+            for dns_server in dns_servers:
+                await semaphore.acquire()
+                asyncio.create_task(dns_lookup(domain, subdomain, dns_server, semaphore))
+
+    elif args.input:
+        async with asyncio.open_file(input_file, 'r') as file:
+            async for domain in file:
+                await semaphore.acquire()
+                dns_server = random.choice(dns_servers)
+                asyncio.create_task(dns_lookup(domain, subdomain, dns_server, semaphore))
+
+
+
+if __name__ == '__main__':
+    import argparse
+    import os
+    import urllib.request
+
+    parser = argparse.ArgumentParser(description='Passive DNS Knocking Tool')
+    parser.add_argument('-d', '--domains', help='Comma seperate list of domains')
+    parser.add_argument('-i', '--input', help='File containing list of domains')
+    parser.add_argument('-s', '--subdomain', help='Subdomain to look up')
+    parser.add_argument('-c', '--concurrency', type=int, default=50, help='Concurrency limit')
+    parser.add_argument('-r', '--resolvers', help='File containing list of DNS resolvers (uses public-dns.info if not specified)')
+    args = parser.parse_args()
+
+    if not args.input and not args.domain:
+        raise SystemExit('no domains specified')
+    
+    if args.input and args.domain:
+        raise SystemExit('cannot specify both domain and input file')
+    
+    if args.input and not os.path.exists(args.input):
+        raise SystemExit('input file does not exist')
+    
+    if args.resolvers:
+        if os.path.exists(args.resolvers):
+            with open(args.resolvers, 'r') as file:
+                dns_servers = [item.strip() for item in file.readlines() if item.strip()]
+                if not dns_servers:
+                    raise SystemExit('no DNS servers found in file')
+                else:
+                     print(f'Loaded {len(dns_servers):,} DNS servers from file')
+        else:
+            raise SystemExit('DNS servers file does not exist')
+    else:
+        dns_servers = urllib.request.urlopen('https://public-dns.info/nameservers.txt').read().decode().split('\n')
+        print(f'Loaded {len(dns_servers):,} DNS servers from public-dns.info')
+
+    asyncio.run(main(args.input, args.domain, args.subdomain, args.concurrency))
+\ No newline at end of file