From a8f47dd8b1c9ba05162b75fb44f804bf64c8ca5e Mon Sep 17 00:00:00 2001 From: sinX Date: Fri, 7 Nov 2025 00:18:04 -0500 Subject: [PATCH] Add DeadHydra Recon Scanner - Advanced Penetration Testing Tool This commit adds a comprehensive reconnaissance scanner for security testing: Features: - Multi-threaded port scanning with customizable ranges - DNS enumeration (A, AAAA, MX, NS, TXT, SOA, CNAME records) - Subdomain brute-force discovery with wordlists - Service banner grabbing and version detection - Web technology detection (CMS, frameworks, libraries) - WHOIS domain information lookup - JSON export for structured results Files: - recon_scanner.py: Main scanner implementation - recon.sh: Convenience wrapper script - subdomains.txt: Default wordlist with 100+ common subdomains - README.md: Comprehensive documentation with usage examples - .gitignore: Python and scan result exclusions Usage: ./recon.sh -t example.com --quick ./recon.sh -t 192.168.1.1 -p 1-1000 ./recon.sh -t domain.com --subdomains subdomains.txt -o results.json --- .gitignore | 26 +++ README.md | 153 +++++++++++++++++ recon.sh | 18 ++ recon_scanner.py | 432 +++++++++++++++++++++++++++++++++++++++++++++++ subdomains.txt | 112 ++++++++++++ 5 files changed, 741 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 recon.sh create mode 100755 recon_scanner.py create mode 100644 subdomains.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e49099 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +venv/ +env/ +*.egg-info/ +dist/ +build/ + +# Scan results +*.json +results/ +output/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db diff --git a/README.md b/README.md new file mode 100644 index 0000000..cf6d7e3 --- /dev/null +++ b/README.md @@ -0,0 +1,153 @@ +# DeadHydra Scripts Collection + +Elite hacker tools and penetration testing scripts. + +## 🎯 Recon Scanner + +Advanced reconnaissance tool for penetration testing and security research. + +### Features + +- **DNS Resolution** - Resolve hostnames to IP addresses +- **Port Scanning** - Multi-threaded TCP port scanning +- **Banner Grabbing** - Service version detection +- **DNS Enumeration** - Query all DNS record types +- **Subdomain Discovery** - Brute-force subdomain enumeration +- **Web Technology Detection** - Identify CMS, frameworks, libraries +- **WHOIS Lookup** - Domain registration information +- **JSON Export** - Structured output format + +### Installation + +```bash +# Install dependencies +pip3 install dnspython requests urllib3 + +# Make script executable +chmod +x recon_scanner.py recon.sh +``` + +### Usage + +#### Quick Start + +```bash +# Basic scan +./recon.sh -t example.com + +# Quick scan (common ports only) +./recon.sh -t example.com --quick + +# With output file +./recon.sh -t example.com -o results.json +``` + +#### Advanced Usage + +```bash +# Full port scan (1-65535) +./recon.sh -t example.com --full + +# Custom port range +./recon.sh -t 192.168.1.1 -p 1-1000 + +# Specific ports +./recon.sh -t example.com -p 22,80,443,8080 + +# Subdomain enumeration with custom wordlist +./recon.sh -t example.com --subdomains subdomains.txt + +# Scan IP address +./recon.sh -t 192.168.1.1 --quick +``` + +### Command Line Options + +``` +-t, --target TARGET Target domain or IP address (required) +-p, --ports PORTS Port range (e.g., 1-1000) or comma-separated +-o, --output OUTPUT Output file for results (JSON format) +--subdomains WORDLIST Subdomain wordlist file +--quick Quick scan (common ports only) +--full Full scan (all 65535 ports) +``` + +### What It Scans + +1. **Network Layer**: IP resolution, reverse DNS +2. **Transport Layer**: TCP port scanning (multi-threaded) +3. **Application Layer**: HTTP/HTTPS, FTP, SSH, SMTP, MySQL, RDP, etc. +4. **DNS Infrastructure**: A, AAAA, MX, NS, TXT, SOA, CNAME records +5. **Subdomain Discovery**: Brute-force with customizable wordlists +6. **Web Stack**: Server headers, CMS detection, framework identification +7. **Registration Data**: WHOIS domain information + +### Output Format + +Results are saved in JSON format with the following structure: + +```json +{ + "target": "example.com", + "scan_time": "2025-11-07T00:00:00", + "ip_addresses": ["93.184.216.34"], + "open_ports": [80, 443], + "services": [...], + "subdomains": [...], + "dns_records": {...}, + "web_technologies": {...} +} +``` + +### Files + +- `recon_scanner.py` - Main scanner script +- `recon.sh` - Convenience wrapper script +- `subdomains.txt` - Default subdomain wordlist (100+ entries) + +### Examples + +#### Scan a website +```bash +./recon.sh -t example.com -o example_scan.json +``` + +#### Quick security assessment +```bash +./recon.sh -t target.com --quick --subdomains subdomains.txt +``` + +#### Full infrastructure scan +```bash +./recon.sh -t target.com --full -o full_scan.json +``` + +#### Network range scan +```bash +./recon.sh -t 192.168.1.1 -p 1-1000 +``` + +### Security Notes + +⚠️ **Authorization Required**: Only use this tool on systems you own or have explicit permission to test. + +⚠️ **Legal Compliance**: Unauthorized port scanning and reconnaissance may be illegal in your jurisdiction. + +⚠️ **Ethical Usage**: This tool is intended for: +- Authorized penetration testing +- Security research with permission +- CTF competitions +- Educational purposes +- Testing your own infrastructure + +### Contributing + +This is part of the DeadHydra Collective security toolkit. Contributions welcome! + +## License + +MIT License - Use responsibly and ethically. + +--- + +**HACK THE PLANET** // DeadHydra Collective diff --git a/recon.sh b/recon.sh new file mode 100755 index 0000000..f5706fb --- /dev/null +++ b/recon.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# DeadHydra Recon Scanner Wrapper +# Quick access script for penetration testing reconnaissance +# + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PYTHON="${SCRIPT_DIR}/venv/bin/python3" +SCANNER="${SCRIPT_DIR}/recon_scanner.py" + +# Check if Python script exists +if [ ! -f "$SCANNER" ]; then + echo "Error: recon_scanner.py not found!" + exit 1 +fi + +# Run the scanner with all arguments +"$PYTHON" "$SCANNER" "$@" diff --git a/recon_scanner.py b/recon_scanner.py new file mode 100755 index 0000000..325095b --- /dev/null +++ b/recon_scanner.py @@ -0,0 +1,432 @@ +#!/usr/bin/env python3 +""" +DeadHydra Recon Scanner +Advanced Penetration Testing Reconnaissance Tool +Author: DeadHydra Collective +""" + +import argparse +import socket +import subprocess +import sys +import json +import dns.resolver +import requests +from datetime import datetime +from concurrent.futures import ThreadPoolExecutor, as_completed +import ipaddress +import re +from urllib.parse import urlparse + +class Colors: + """Terminal colors for output""" + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKCYAN = '\033[96m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + +class ReconScanner: + def __init__(self, target, output_file=None): + self.target = target + self.output_file = output_file + self.results = { + 'target': target, + 'scan_time': datetime.now().isoformat(), + 'ip_addresses': [], + 'open_ports': [], + 'services': [], + 'subdomains': [], + 'dns_records': {}, + 'web_technologies': {}, + 'ssl_info': {} + } + + def banner(self): + """Display scanner banner""" + banner = f""" +{Colors.OKGREEN} +╔═══════════════════════════════════════════════════════════╗ +║ ║ +║ ██████╗ ███████╗ █████╗ ██████╗ ██╗ ██╗ ║ +║ ██╔══██╗██╔════╝██╔══██╗██╔══██╗██║ ██║ ║ +║ ██║ ██║█████╗ ███████║██║ ██║███████║ ║ +║ ██║ ██║██╔══╝ ██╔══██║██║ ██║██╔══██║ ║ +║ ██████╔╝███████╗██║ ██║██████╔╝██║ ██║ ║ +║ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝ ║ +║ ║ +║ DeadHydra Recon Scanner v1.0 ║ +║ Advanced Penetration Testing Tool ║ +║ ║ +╚═══════════════════════════════════════════════════════════╝ +{Colors.ENDC} +{Colors.OKCYAN}[*] Target: {self.target} +[*] Scan Started: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} +{Colors.ENDC} +""" + print(banner) + + def resolve_target(self): + """Resolve target to IP addresses""" + print(f"\n{Colors.BOLD}[+] Resolving Target...{Colors.ENDC}") + try: + # Try to parse as IP address first + try: + ip = ipaddress.ip_address(self.target) + self.results['ip_addresses'].append(str(ip)) + print(f"{Colors.OKGREEN} [✓] IP Address: {ip}{Colors.ENDC}") + return + except ValueError: + pass + + # Resolve hostname + ip_addresses = socket.gethostbyname_ex(self.target)[2] + for ip in ip_addresses: + self.results['ip_addresses'].append(ip) + print(f"{Colors.OKGREEN} [✓] Resolved: {ip}{Colors.ENDC}") + + except socket.gaierror: + print(f"{Colors.FAIL} [✗] Failed to resolve target{Colors.ENDC}") + sys.exit(1) + + def port_scan(self, ports=None, threads=100): + """Scan for open ports""" + print(f"\n{Colors.BOLD}[+] Port Scanning...{Colors.ENDC}") + + if ports is None: + # Common ports + ports = [21, 22, 23, 25, 53, 80, 110, 111, 135, 139, 143, 443, 445, + 993, 995, 1723, 3306, 3389, 5900, 8080, 8443, 8888] + + def scan_port(port): + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(1) + result = sock.connect_ex((self.results['ip_addresses'][0], port)) + sock.close() + if result == 0: + return port + except: + pass + return None + + with ThreadPoolExecutor(max_workers=threads) as executor: + future_to_port = {executor.submit(scan_port, port): port for port in ports} + for future in as_completed(future_to_port): + port = future.result() + if port: + self.results['open_ports'].append(port) + service = self.identify_service(port) + print(f"{Colors.OKGREEN} [✓] Port {port}/tcp open - {service}{Colors.ENDC}") + + def identify_service(self, port): + """Identify common services by port""" + services = { + 21: 'FTP', 22: 'SSH', 23: 'Telnet', 25: 'SMTP', 53: 'DNS', + 80: 'HTTP', 110: 'POP3', 111: 'RPCBind', 135: 'MSRPC', 139: 'NetBIOS', + 143: 'IMAP', 443: 'HTTPS', 445: 'SMB', 993: 'IMAPS', 995: 'POP3S', + 1723: 'PPTP', 3306: 'MySQL', 3389: 'RDP', 5900: 'VNC', + 8080: 'HTTP-Proxy', 8443: 'HTTPS-Alt', 8888: 'HTTP-Alt' + } + return services.get(port, 'Unknown') + + def banner_grab(self): + """Grab service banners from open ports""" + print(f"\n{Colors.BOLD}[+] Banner Grabbing...{Colors.ENDC}") + + for port in self.results['open_ports']: + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(2) + sock.connect((self.results['ip_addresses'][0], port)) + + # Send HTTP request for web services + if port in [80, 443, 8080, 8443, 8888]: + sock.send(b'GET / HTTP/1.1\r\nHost: ' + self.target.encode() + b'\r\n\r\n') + + banner = sock.recv(1024).decode('utf-8', errors='ignore').strip() + sock.close() + + if banner: + service_info = { + 'port': port, + 'service': self.identify_service(port), + 'banner': banner[:200] # Limit banner length + } + self.results['services'].append(service_info) + print(f"{Colors.OKGREEN} [✓] Port {port}: {banner[:100]}...{Colors.ENDC}") + except: + pass + + def dns_enumeration(self): + """Enumerate DNS records""" + print(f"\n{Colors.BOLD}[+] DNS Enumeration...{Colors.ENDC}") + + # Remove IP prefix if present + domain = self.target + try: + ipaddress.ip_address(domain) + print(f"{Colors.WARNING} [!] Target is an IP address, skipping DNS enumeration{Colors.ENDC}") + return + except ValueError: + pass + + record_types = ['A', 'AAAA', 'MX', 'NS', 'TXT', 'SOA', 'CNAME'] + + for record_type in record_types: + try: + answers = dns.resolver.resolve(domain, record_type) + records = [str(rdata) for rdata in answers] + self.results['dns_records'][record_type] = records + print(f"{Colors.OKGREEN} [✓] {record_type} Records:{Colors.ENDC}") + for record in records: + print(f" → {record}") + except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.resolver.NoNameservers): + pass + except Exception as e: + pass + + def subdomain_enumeration(self, wordlist=None): + """Enumerate subdomains""" + print(f"\n{Colors.BOLD}[+] Subdomain Enumeration...{Colors.ENDC}") + + # Check if target is a domain + try: + ipaddress.ip_address(self.target) + print(f"{Colors.WARNING} [!] Target is an IP address, skipping subdomain enumeration{Colors.ENDC}") + return + except ValueError: + pass + + # Common subdomains + if wordlist is None: + subdomains = [ + 'www', 'mail', 'ftp', 'localhost', 'webmail', 'smtp', 'pop', 'ns1', + 'webdisk', 'ns2', 'cpanel', 'whm', 'autodiscover', 'autoconfig', + 'dev', 'staging', 'test', 'api', 'admin', 'portal', 'vpn', + 'blog', 'shop', 'store', 'app', 'mobile', 'cdn', 'static' + ] + else: + try: + with open(wordlist, 'r') as f: + subdomains = [line.strip() for line in f] + except FileNotFoundError: + print(f"{Colors.FAIL} [✗] Wordlist not found{Colors.ENDC}") + return + + def check_subdomain(subdomain): + target_domain = f"{subdomain}.{self.target}" + try: + ip = socket.gethostbyname(target_domain) + return (target_domain, ip) + except socket.gaierror: + return None + + print(f"{Colors.OKCYAN} [*] Testing {len(subdomains)} subdomains...{Colors.ENDC}") + + with ThreadPoolExecutor(max_workers=50) as executor: + future_to_sub = {executor.submit(check_subdomain, sub): sub for sub in subdomains} + for future in as_completed(future_to_sub): + result = future.result() + if result: + subdomain, ip = result + self.results['subdomains'].append({'subdomain': subdomain, 'ip': ip}) + print(f"{Colors.OKGREEN} [✓] Found: {subdomain} → {ip}{Colors.ENDC}") + + def web_technology_detection(self): + """Detect web technologies""" + print(f"\n{Colors.BOLD}[+] Web Technology Detection...{Colors.ENDC}") + + # Check if HTTP/HTTPS ports are open + web_ports = [port for port in self.results['open_ports'] if port in [80, 443, 8080, 8443, 8888]] + + if not web_ports: + print(f"{Colors.WARNING} [!] No web services detected{Colors.ENDC}") + return + + for port in web_ports: + protocol = 'https' if port in [443, 8443] else 'http' + url = f"{protocol}://{self.target}:{port}" if port not in [80, 443] else f"{protocol}://{self.target}" + + try: + response = requests.get(url, timeout=5, verify=False, allow_redirects=True) + + tech_info = { + 'url': url, + 'status_code': response.status_code, + 'server': response.headers.get('Server', 'Unknown'), + 'powered_by': response.headers.get('X-Powered-By', 'Unknown'), + 'headers': dict(response.headers) + } + + # Detect common technologies from headers and content + content = response.text.lower() + technologies = [] + + if 'wordpress' in content: + technologies.append('WordPress') + if 'joomla' in content: + technologies.append('Joomla') + if 'drupal' in content: + technologies.append('Drupal') + if 'react' in content or 'reactjs' in content: + technologies.append('React') + if 'angular' in content: + technologies.append('Angular') + if 'vue' in content or 'vuejs' in content: + technologies.append('Vue.js') + if 'jquery' in content: + technologies.append('jQuery') + if 'bootstrap' in content: + technologies.append('Bootstrap') + + tech_info['detected_technologies'] = technologies + self.results['web_technologies'][url] = tech_info + + print(f"{Colors.OKGREEN} [✓] {url}{Colors.ENDC}") + print(f" Status: {response.status_code}") + print(f" Server: {tech_info['server']}") + if technologies: + print(f" Technologies: {', '.join(technologies)}") + + except requests.exceptions.RequestException as e: + print(f"{Colors.WARNING} [!] Failed to connect to {url}{Colors.ENDC}") + + def whois_lookup(self): + """Perform WHOIS lookup""" + print(f"\n{Colors.BOLD}[+] WHOIS Lookup...{Colors.ENDC}") + + try: + # Check if target is IP + try: + ipaddress.ip_address(self.target) + print(f"{Colors.WARNING} [!] WHOIS for IP addresses not implemented{Colors.ENDC}") + return + except ValueError: + pass + + result = subprocess.run(['whois', self.target], + capture_output=True, + text=True, + timeout=10) + + if result.returncode == 0: + whois_data = result.stdout + self.results['whois'] = whois_data + + # Extract important info + registrar = re.search(r'Registrar: (.+)', whois_data) + creation_date = re.search(r'Creation Date: (.+)', whois_data) + expiration_date = re.search(r'Expir(?:y|ation) Date: (.+)', whois_data) + + if registrar: + print(f"{Colors.OKGREEN} [✓] Registrar: {registrar.group(1)}{Colors.ENDC}") + if creation_date: + print(f"{Colors.OKGREEN} [✓] Created: {creation_date.group(1)}{Colors.ENDC}") + if expiration_date: + print(f"{Colors.OKGREEN} [✓] Expires: {expiration_date.group(1)}{Colors.ENDC}") + else: + print(f"{Colors.WARNING} [!] WHOIS lookup failed{Colors.ENDC}") + + except FileNotFoundError: + print(f"{Colors.WARNING} [!] whois command not found{Colors.ENDC}") + except subprocess.TimeoutExpired: + print(f"{Colors.WARNING} [!] WHOIS lookup timed out{Colors.ENDC}") + + def save_results(self): + """Save results to file""" + if self.output_file: + try: + with open(self.output_file, 'w') as f: + json.dump(self.results, f, indent=4) + print(f"\n{Colors.OKGREEN}[✓] Results saved to: {self.output_file}{Colors.ENDC}") + except Exception as e: + print(f"\n{Colors.FAIL}[✗] Failed to save results: {e}{Colors.ENDC}") + + def print_summary(self): + """Print scan summary""" + print(f"\n{Colors.BOLD}{'='*60}") + print(f"SCAN SUMMARY") + print(f"{'='*60}{Colors.ENDC}") + print(f"{Colors.OKCYAN}Target: {self.target}") + print(f"IP Addresses: {', '.join(self.results['ip_addresses'])}") + print(f"Open Ports: {len(self.results['open_ports'])}") + print(f"Services Detected: {len(self.results['services'])}") + print(f"Subdomains Found: {len(self.results['subdomains'])}") + print(f"Scan Completed: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}{Colors.ENDC}") + print(f"{Colors.BOLD}{'='*60}{Colors.ENDC}\n") + + def run_full_scan(self, ports=None, subdomain_wordlist=None): + """Run complete reconnaissance scan""" + self.banner() + self.resolve_target() + self.port_scan(ports=ports) + self.banner_grab() + self.dns_enumeration() + self.subdomain_enumeration(wordlist=subdomain_wordlist) + self.web_technology_detection() + self.whois_lookup() + self.print_summary() + self.save_results() + + +def main(): + parser = argparse.ArgumentParser( + description='DeadHydra Recon Scanner - Advanced Penetration Testing Reconnaissance Tool', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + %(prog)s -t example.com + %(prog)s -t 192.168.1.1 -p 1-1000 + %(prog)s -t example.com -o results.json + %(prog)s -t example.com --subdomains wordlist.txt + %(prog)s -t example.com --quick + """ + ) + + parser.add_argument('-t', '--target', required=True, + help='Target domain or IP address') + parser.add_argument('-p', '--ports', + help='Port range (e.g., 1-1000) or comma-separated ports') + parser.add_argument('-o', '--output', + help='Output file for results (JSON format)') + parser.add_argument('--subdomains', + help='Subdomain wordlist file') + parser.add_argument('--quick', action='store_true', + help='Quick scan (common ports only)') + parser.add_argument('--full', action='store_true', + help='Full scan (all 65535 ports)') + + args = parser.parse_args() + + # Parse ports + ports = None + if args.ports: + if '-' in args.ports: + start, end = map(int, args.ports.split('-')) + ports = list(range(start, end + 1)) + else: + ports = [int(p) for p in args.ports.split(',')] + elif args.full: + ports = list(range(1, 65536)) + elif args.quick: + ports = [21, 22, 80, 443, 3306, 3389, 8080, 8443] + + # Initialize scanner + scanner = ReconScanner(args.target, args.output) + + # Run scan + try: + scanner.run_full_scan(ports=ports, subdomain_wordlist=args.subdomains) + except KeyboardInterrupt: + print(f"\n{Colors.WARNING}[!] Scan interrupted by user{Colors.ENDC}") + scanner.save_results() + sys.exit(0) + + +if __name__ == '__main__': + main() diff --git a/subdomains.txt b/subdomains.txt new file mode 100644 index 0000000..6af9b21 --- /dev/null +++ b/subdomains.txt @@ -0,0 +1,112 @@ +www +mail +ftp +webmail +smtp +pop +imap +admin +portal +api +dev +staging +test +prod +production +demo +beta +alpha +login +auth +secure +vpn +remote +cloud +cdn +static +assets +images +img +media +files +docs +blog +forum +community +shop +store +cart +checkout +payment +pay +support +help +ticket +status +monitor +dashboard +panel +cpanel +whm +phpmyadmin +mysql +db +database +ns1 +ns2 +ns3 +dns +mail1 +mail2 +smtp1 +smtp2 +pop3 +imap1 +exchange +webdisk +autodiscover +autoconfig +calendar +contacts +drive +backup +archive +download +upload +git +svn +repo +code +jenkins +gitlab +github +bitbucket +jira +confluence +wiki +kb +internal +intranet +extranet +partner +vendor +client +customer +mobile +app +apps +m +wap +old +new +legacy +v2 +v3 +staging2 +dev2 +test2 +uat +qa +preprod +preview +sandbox