Skip to content

Commit 001b2df

Browse files
committed
refactor(subbrute): replace dnspython with socket for dns resolution and update default wordlist filename and improve user prompts
1 parent 84d4e07 commit 001b2df

File tree

4 files changed

+35
-40
lines changed

4 files changed

+35
-40
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ share/python-wheels/
2727
MANIFEST
2828
*.txt
2929
!structure.txt
30-
!wordlist.txt
30+
!wordlist_example.txt
3131

3232
# PyInstaller
3333
# Usually these files are written by a python script from a template

bugscanx/modules/scrapers/subfinder/subbrute/subbrute.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
from concurrent.futures import ThreadPoolExecutor, as_completed
33

4-
from bugscanx.utils.common import get_input
4+
from bugscanx.utils.common import get_input, get_confirm
55
from .logger import SubBruteConsole
66
from .utils import DomainValidator, SubdomainBruteforcer, CursorManager
77

@@ -14,7 +14,7 @@ def __init__(self, wordlist_path=None, max_workers=50, dns_timeout=3, enable_wil
1414

1515
if wordlist_path is None:
1616
current_dir = os.path.dirname(os.path.abspath(__file__))
17-
wordlist_path = os.path.join(current_dir, 'wordlist.txt')
17+
wordlist_path = os.path.join(current_dir, 'wordlist_example.txt')
1818

1919
self.bruteforcer = SubdomainBruteforcer(
2020
wordlist_path=wordlist_path,
@@ -133,18 +133,16 @@ def main():
133133
return
134134

135135
output_file = get_input("Enter output filename", default=default_output)
136-
137-
use_custom_wordlist = get_input("Use custom wordlist?", "choice",
138-
choices=["No", "Yes"]) == "Yes"
136+
137+
use_custom_wordlist = get_confirm(" Use custom wordlist?")
138+
139139
wordlist_path = get_input("Enter wordlist path", "file") if use_custom_wordlist else None
140140

141141
max_workers = int(get_input("Max concurrent threads per domain",
142142
default="50"))
143143
dns_timeout = int(get_input("DNS timeout in seconds",
144144
default="3"))
145-
146-
enable_wildcard_filtering = get_input("Enable wildcard filtering?", "choice",
147-
choices=["Yes", "No"]) == "Yes"
145+
enable_wildcard_filtering = get_confirm(" Enable wildcard filtering?")
148146

149147
subbrute = SubBrute(
150148
wordlist_path=wordlist_path,

bugscanx/modules/scrapers/subfinder/subbrute/utils.py

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import re
22
import random
33
import string
4-
import dns.resolver
5-
import dns.exception
4+
import socket
65
from concurrent.futures import ThreadPoolExecutor, as_completed
76

87

@@ -39,15 +38,25 @@ def filter_valid_subdomains(subdomains, domain):
3938

4039

4140
class WildcardDetector:
42-
def __init__(self, dns_resolver):
43-
self.dns_resolver = dns_resolver
41+
def __init__(self, timeout=3):
4442
self.wildcard_ips = set()
4543
self.wildcard_detected = False
44+
self.timeout = timeout
4645

4746
def _generate_random_subdomain(self, length=10):
4847
random_string = ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
4948
return f"{random_string}-nonexistent-{random.randint(10000, 99999)}"
5049

50+
def _resolve_domain(self, domain):
51+
try:
52+
socket.setdefaulttimeout(self.timeout)
53+
ip = socket.gethostbyname(domain)
54+
return True, ip
55+
except (socket.gaierror, socket.timeout):
56+
return False, None
57+
except Exception:
58+
return False, None
59+
5160
def detect_wildcards(self, domain, test_count=5):
5261
self.wildcard_ips.clear()
5362
self.wildcard_detected = False
@@ -58,7 +67,7 @@ def detect_wildcards(self, domain, test_count=5):
5867
random_subdomain = self._generate_random_subdomain()
5968
test_domain = f"{random_subdomain}.{domain}"
6069

61-
exists, ip = self.dns_resolver.check_subdomain(test_domain)
70+
exists, ip = self._resolve_domain(test_domain)
6271
if exists and ip:
6372
ips = [ip] if isinstance(ip, str) else ip
6473
for single_ip in ips:
@@ -90,34 +99,22 @@ def get_wildcard_ips(self):
9099

91100

92101
class DNSResolver:
93-
def __init__(self, timeout=3, nameservers=None):
94-
self.resolver = dns.resolver.Resolver()
95-
self.resolver.timeout = timeout
96-
self.resolver.lifetime = timeout
97-
98-
if nameservers:
99-
self.resolver.nameservers = nameservers
100-
else:
101-
self.resolver.nameservers = ['8.8.8.8', '1.1.1.1', '8.8.4.4', '1.0.0.1']
102-
103-
def resolve(self, hostname, record_type='A'):
102+
def __init__(self, timeout=3):
103+
socket.setdefaulttimeout(timeout)
104+
105+
def resolve(self, hostname):
104106
try:
105-
answers = self.resolver.resolve(hostname, record_type)
106-
if record_type == 'A' or record_type == 'AAAA':
107-
ips = [str(answer) for answer in answers]
108-
return True, ips[0] if len(ips) == 1 else ips
109-
else:
110-
return True, [str(answer) for answer in answers]
111-
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer,
112-
dns.resolver.NoNameservers, dns.exception.Timeout,
113-
Exception):
107+
108+
ip = socket.gethostbyname(hostname)
109+
return True, ip
110+
except (socket.gaierror, socket.timeout):
111+
return False, None
112+
except Exception:
114113
return False, None
115114

116115
def check_subdomain(self, subdomain):
117116
success, result = self.resolve(subdomain)
118-
if success:
119-
return True, result if isinstance(result, str) else result[0]
120-
return False, None
117+
return success, result
121118

122119

123120
class WordlistManager:
@@ -146,10 +143,10 @@ def get_wordlist_size(self):
146143

147144

148145
class SubdomainBruteforcer:
149-
def __init__(self, wordlist_path, max_workers=50, timeout=3, nameservers=None, enable_wildcard_filtering=True):
146+
def __init__(self, wordlist_path, max_workers=50, timeout=3, enable_wildcard_filtering=True):
150147
self.wordlist_manager = WordlistManager(wordlist_path)
151-
self.dns_resolver = DNSResolver(timeout=timeout, nameservers=nameservers)
152-
self.wildcard_detector = WildcardDetector(self.dns_resolver)
148+
self.dns_resolver = DNSResolver(timeout=timeout)
149+
self.wildcard_detector = WildcardDetector(timeout=timeout)
153150
self.max_workers = max_workers
154151
self.wordlist = []
155152
self.enable_wildcard_filtering = enable_wildcard_filtering

0 commit comments

Comments
 (0)