MrCl0wnLab/SimpleReconSubdomain

GitHub: MrCl0wnLab/SimpleReconSubdomain

Stars: 31 | Forks: 7

# SimpleReconSubdomain v2
![Screenshot](/assets/screenshot/banner.png)

Passive and active subdomain enumeration tool for OSINT and reconnaissance workflows. Built with async Python - queries **47 sources** (39 passive + 8 active) in parallel with no external shell dependencies. Techniques inspired by **subfinder**, **amass**, **puredns** and **subjack**: multi-probe wildcard detection, DNSSEC NSEC zone walking, TLS SAN extraction, SRV record mining, two-pass trusted-resolver validation, recursive enumeration, JavaScript link extraction, and subdomain-takeover fingerprinting. Author: MrCl0wn Blog: https://blog.mrcl0wn.com GitHub: https://github.com/MrCl0wnLab Twitter: https://twitter.com/MrCl0wnLab ## WARNING +------------------------------------------------------------------------------+ | [!] Legal disclaimer: Usage of SimpleReconSubdomain for attacking | | targets without prior mutual consent is illegal. | | It is the end user's responsibility to obey all applicable | | local, state and federal laws. | | Developers assume no liability and are not responsible for any misuse or | | damage caused by this program. | +------------------------------------------------------------------------------+ ## Table of Contents - [Installation](#installation) - [API Keys](#api-keys) - [Usage](#usage) - [Profiles](#profiles) - [Run-Config Presets](#run-config-presets) - [Passive vs Active Modules](#passive-vs-active-modules) - [Sources](#sources) - [DNS Brute-force](#dns-brute-force) - [TLD Brute-force](#tld-brute-force) - [Advanced Techniques](#advanced-techniques) - [Subdomain Takeover Detection](#subdomain-takeover-detection) - [Output Formats](#output-formats) - [Chaining with Other Tools](#chaining-with-other-tools) - [Creating a New Module](#creating-a-new-module) ## Installation git clone https://github.com/MrCl0wnLab/SimpleReconSubdomain cd SimpleReconSubdomain pip install -r requirements.txt **Dependencies** (`requirements.txt`): | Package | Purpose | |---|---| | `httpx` | Async HTTP client for all passive sources and resolver URL download | | `aiodns` | Async DNS resolver for brute-force and validation | | `dnspython` | Zone transfer (AXFR), DNS record mining, NSEC zone walking, SRV enumeration | ## API Keys API keys are stored in `config/api_keys.json` (gitignored to prevent leaks). { "alienvault_otx": "", "hackertarget": "", "urlscan": "", "virustotal": "", "securitytrails": "", "shodan": "", "github_token": "", "censys_id": "", "censys_secret": "", "grayhatwarfare_token": "", "leakix_token": "", "fullhunt_token": "", "chaos_key": "", "c99_key": "", "netlas_key": "", "onyphe_key": "", "greynoise_key": "", "fofa_key": "", "pulsedive_key": "", "intelx_key": "", "publicwww_key": "", "merklemap_key": "", "bevigil_key": "", "hunterhow_key": "", "circl_user": "", "circl_pass": "" } **Where to get each key:** | Key | URL | |---|---| | `alienvault_otx` | https://otx.alienvault.com → Settings → API Integration | | `hackertarget` | https://hackertarget.com/membership | | `urlscan` | https://urlscan.io/user/signup | | `virustotal` | https://www.virustotal.com/gui/join-us | | `securitytrails` | https://securitytrails.com/app/account | | `shodan` | https://account.shodan.io | | `censys_id` / `censys_secret` | https://search.censys.io/account/api | | `github_token` | https://github.com/settings/tokens (scope: `public_repo`) | | `grayhatwarfare_token` | https://grayhatwarfare.com/account | | `leakix_token` | https://leakix.net/login → API Keys | | `fullhunt_token` | https://fullhunt.io/user/api | | `chaos_key` | https://chaos.projectdiscovery.io → API Key | | `c99_key` | https://api.c99.nl → Sign up | | `netlas_key` | https://app.netlas.io/profile/ → API Keys | | `onyphe_key` | https://www.onyphe.io/login/ → API | | `greynoise_key` | https://viz.greynoise.io/account/ | | `fofa_key` | https://fofa.so/userInfo | | `pulsedive_key` | https://pulsedive.com/api/ | | `intelx_key` | https://intelx.io/account?tab=developer | | `publicwww_key` | https://publicwww.com/api.html | | `merklemap_key` | https://www.merklemap.com/dashboard/api (paid subscription required) | | `bevigil_key` | https://bevigil.com/osint-api → Sign up | | `hunterhow_key` | https://hunter.how/api → Get API key | | `circl_user` / `circl_pass` | https://www.circl.lu/services/passive-dns/ → Request access (optional; free unauthenticated tier available) | ## Usage ### Basic # Single domain python simplerecon.py -d target.com # List of domains python simplerecon.py -l domains.txt # List available sources python simplerecon.py --list-sources # List available profiles (curated source groups) python simplerecon.py --list-profiles # Print built-in usage examples and exit python simplerecon.py --list-examples # Run a predefined profile (no need to spell out sources) python simplerecon.py -d target.com --profile fast python simplerecon.py -d target.com --profile osint --verify-live
![Screenshot](/assets/screenshot/img.png)
### OSINT Context Examples **Bug bounty - map external attack surface (passive only):** python simplerecon.py -d megacorp.com \ --sources crtsh,virustotal,shodan,censys,github,chaos \ --output json --outfile megacorp_subs.json **Full enumeration - passive + brute-force + live verification:** python simplerecon.py -d target.com \ --brute wordlists/subdomains-top1million-20000.txt \ --resolvers config/resolvers.txt \ --wildcard-tests 5 \ --validate-resolvers \ --verify-live \ --output json \ --outfile target_full.json python simplerecon.py -d target.com \ --brute wordlists/all.txt \ --resolvers https://public-dns.info/nameservers-all.txt \ --check-resolvers \ --validate-resolvers \ --threads 40 **Deep recon - include active sources and recursive enumeration:** python simplerecon.py -d target.com \ --sources crtsh,certspotter,github,chaos,nsec_walk,srv_enum \ --brute wordlists/top5000.txt \ --recursive --recursive-depth 2 \ --verify-live \ --output json --outfile deep_recon.json **DNSSEC zone walking (requires NSEC, not NSEC3):** python simplerecon.py -d target.com --sources nsec_walk -v **Asset discovery from a domain list:** python simplerecon.py -l scope.txt --output json --outfile all_subs.json --timeout 60 **Quiet mode - pipe subdomains directly to another tool:** python simplerecon.py -d target.com --no-banner | httpx -silent ### All Flags Target: -d DOMAIN Single target domain -l FILE File with one domain per line --stdin Read domains from stdin (one per line); enables pipe-friendly use Output: -o {txt,json,csv,ndjson} Output format (default: txt). ndjson = one compact JSON line per subdomain - ideal for jq piping --outfile FILE Write output to file Performance: -t N Thread multiplier for brute-force concurrency (default: 8) --timeout N HTTP/DNS timeout in seconds (default: 30) --rate-limit N Max concurrent HTTP requests per source (0 = unlimited) Network: --proxy URL Route all HTTP requests through a proxy (e.g. http://127.0.0.1:8080 or socks5://host:port) --user-agent UA Override User-Agent for all source HTTP requests Source control: --profile PROFILE Run a predefined source group (fast, stealth, osint, code, active, full). Overrides --sources. --sources LIST Comma-separated sources (default: all) --exclude LIST Comma-separated sources to exclude (applied after --sources/--profile) --no-passive Skip passive sources; run active/brute only --list-sources Print all sources with descriptions and exit --list-profiles Print all profiles with their source sets and exit --list-examples Print built-in usage examples and exit Run-config: --config FILE Load CLI argument defaults from a JSON preset file. Only keys absent from the command line are applied; explicit CLI flags always win. Template: config/run_config.example.json Brute-force: --brute WORDLIST Wordlist path for DNS brute-force --resolvers FILE_OR_URL DNS resolver IPs - local file or https:// URL (e.g. config/resolvers.txt or https://public-dns.info/nameservers-all.txt) --check-resolvers Test each resolver against example.com before brute-force; remove non-responsive ones (PureDNS technique) --wildcard-tests N Random probes for wildcard detection (default: 3) Higher values reduce false negatives on load-balanced DNS --validate-resolvers Re-validate results against Google/Cloudflare after brute-force to eliminate DNS-poisoned false positives (PureDNS two-pass) --permute Generate Altdns-style permutations from found subdomains --tld-brute [FILE] Discover live TLD variants of the target (e.g. target.net, target.io). Strips the current TLD, resolves {base}.{tld} for every entry in the wordlist. Optional FILE overrides the default config/tlds.txt (~250 TLDs). Results are stored separately as tld_variants in all output formats. Post-processing: --verify-live HTTP/HTTPS probe; also extracts TLS certificate SANs (Amass technique) and fingerprints potential subdomain takeovers (Subjack technique) --recursive Re-enumerate discovered subdomains as new targets (Subfinder technique) --recursive-depth N Max recursion depth when --recursive is enabled (default: 1) Display: -v [LEVEL] Verbose level 1–4 (1=zero results, 2=+HTTP codes, 3=+body, 4=+exceptions) -q, --quiet Results only; suppress all process messages --no-banner Suppress banner and all process output (clean pipe mode) --no-color Disable ANSI colors
![Screenshot](/assets/screenshot/img3.png)
## Profiles Profiles are curated source groups defined in [config/profiles.json](config/profiles.json). Use `--profile NAME` instead of typing long `--sources` lists. Profiles may also set defaults (e.g. `rate_limit`) automatically. python simplerecon.py --list-profiles python simplerecon.py -d target.com --profile fast | Profile | Description | Sources | |---|---|---| | `fast` | Quick scan - fastest no-auth sources only | `crtsh`, `certspotter`, `hackertarget`, `rapiddns`, `jldc`, `alienvault`, `anubisdb`, `subdomaincenter`, `urlhaus`, `circl`, `bing` | | `stealth` | Minimal footprint - passive only, rate-limited (`rate_limit=2`) | `crtsh`, `certspotter`, `wayback`, `commoncrawl`, `robtex`, `anubisdb` | | `osint` | Code repos + threat intel + CT logs + asset DBs | `crtsh`, `certspotter`, `alienvault`, `virustotal`, `shodan`, `github`, `grep_app`, `threatminer`, `anubisdb`, `subdomaincenter`, `hackertarget`, `rapiddns`, `urlscan`, `bevigil`, `hunterhow`, `urlhaus`, `circl`, `bing` | | `code` | Code search only | `github`, `grep_app` | | `active` | Active techniques only | `zone_transfer`, `dns_mining`, `nsec_walk`, `srv_enum`, `js_scrape`, `ptr_sweep`, `vhost_probe` | | `full` | All available passive and active sources | `all` | Add or edit profiles by modifying [config/profiles.json](config/profiles.json): { "myprofile": { "description": "My custom set", "sources": ["crtsh", "github", "shodan"], "options": {"rate_limit": 5} } } ## Run-Config Presets A run-config is a JSON file that stores CLI argument defaults, allowing you to run repeatable scans without long command lines. python simplerecon.py -d target.com --config config/run_config.example.json python simplerecon.py -d target.com --config my_scan.json **Precedence (highest → lowest):** 1. Explicit CLI flags (always win) 2. Values from the `--config` JSON file 3. Built-in argparse defaults Only keys present in the JSON are applied; unknown keys are silently ignored so configs stay forward/backward compatible. A minimal config is perfectly valid — you only need to include the keys you want to set: { "profile": "osint", "verify_live": true, "output": "json", "outfile": "results.json" } The annotated template at [config/run_config.example.json](config/run_config.example.json) documents every available key. Copy and edit it to create your own preset. # List-examples shows ready-to-copy command patterns python simplerecon.py --list-examples ## Passive vs Active Modules ### Passive Passive sources query **third-party databases, APIs, and public indexes**. No packet is sent to the target's infrastructure. - Safe to run during passive recon phases - Invisible to the target's security monitoring - Examples: Certificate Transparency logs, Shodan, VirusTotal, GitHub code search, Common Crawl ### Active Active sources **communicate directly with the target's DNS servers**. The target can observe this traffic. | Module | What it does | Detection level | |---|---|---| | `zone_transfer` | AXFR attempt on all nameservers | **High** - connects to target NS | | `dns_mining` | SPF / DMARC / MX / TXT record queries | **Moderate** - DNS queries to target NS | | `nsec_walk` | DNSSEC NSEC chain walking to enumerate entire zone | **High** - queries authoritative NS directly | | `srv_enum` | SRV record enumeration for ~70 common service prefixes | **Moderate** - DNS queries to public resolvers | | `js_scrape` | Fetches the target's root HTML, downloads every linked `.js` file, and regex-extracts subdomains hardcoded in JS bundles | **High** - direct HTTP requests to target | | `spider` | Crawls the target site following `` links (max depth 2, 50 pages), extracts subdomains from every page | **High** - direct HTTP requests to target | | `ptr_sweep` | Reverse-DNS PTR sweep on /24 blocks containing target IPs | **Moderate** - DNS queries to public resolvers | | `vhost_probe` | Virtual-host brute-force via HTTP Host-header fuzzing | **High** - direct HTTP requests to target | Active modules are included in `--sources all`. To run them explicitly: # Run only active sources python simplerecon.py -d target.com --no-passive --sources zone_transfer,dns_mining,nsec_walk,srv_enum,js_scrape,spider # Mix passive + specific active python simplerecon.py -d target.com --sources crtsh,shodan,nsec_walk,srv_enum,js_scrape # Or just use the curated active profile python simplerecon.py -d target.com --profile active ## Sources python simplerecon.py --list-sources ### Passive Sources (39) | Source | Requires key | Notes | |---|---|---| | `rapiddns` | No | DNS dataset | | `jldc` | No | Anubis subdomain DB | | `crtsh` | No | Certificate Transparency | | `certspotter` | No | Certificate Transparency | | `merklemap` | Required | CT log aggregator (alternative to crt.sh) - paid subscription required | | `anubisdb` | No | jonlu.ca passive DNS subdomain database | | `subdomaincenter` | No | Netcraft-backed free subdomain index | | `threatminer` | No | ThreatMiner passive DNS / threat intel | | `urlscan` | Optional | Higher rate limit with key | | `hackertarget` | Optional | Higher rate limit with key | | `wayback` | No | web.archive.org CDX API (paginated, up to 200k entries) | | `commoncrawl` | No | Common Crawl CDX API - independent historical crawl data | | `robtex` | No | Passive DNS | | `alienvault` | Optional | OTX threat intelligence | | `bufferover` | No | Rapid7 FDNS via TLS | | `dnsdumpster` | No | DNS recon tool (web scraping) | | `github` | Required | Code search for hardcoded domain references | | `grep_app` | No | grep.app GitHub code search | | `virustotal` | Required | VT subdomains endpoint | | `securitytrails` | Required | DNS history | | `censys` | Required | Certificate search | | `shodan` | Required | DNS domain lookup | | `grayhatwarfare` | Required | Public cloud buckets (AWS/Azure/GCP) | | `leakix` | Optional | Exposed services and cloud assets | | `fullhunt` | Required | Full internet host & subdomain index | | `chaos` | Required | ProjectDiscovery continuously updated subdomain DB | | `c99` | Required | C99.nl subdomain finder | | `netlas` | Required | Internet-wide asset and subdomain discovery | | `onyphe` | Required | Cyber defense search engine | | `greynoise` | Required | Internet noise / passive scanner data | | `fofa` | Optional | FOFA internet asset search (free scrape fallback when no key) | | `pulsedive` | Optional | Threat-intel observable lookup | | `intelx` | Required | IntelligenceX leaked data search | | `publicwww` | Required | Source-code search across the public web | | `bevigil` | Required | BeVigil OSINT - subdomains extracted from mobile apps | | `hunterhow` | Required | Hunter.how global asset database | | `urlhaus` | No | URLhaus abuse.ch malicious URL database - no auth needed | | `circl` | No (Optional Basic auth) | CIRCL Passive DNS - public free tier; key gives higher rate | | `bing` | No | Bing search - multi-template UA-rotating anti-bot scraping | ### Active Sources (8) | Source | Requires key | Notes | |---|---|---| | `zone_transfer` | No | DNS Zone Transfer (AXFR) | | `dns_mining` | No | SPF / DMARC / MX record mining | | `nsec_walk` | No | DNSSEC NSEC zone walking | | `srv_enum` | No | SRV record enumeration (~70 service prefixes) | | `js_scrape` | No | Fetches target HTML + linked JS files, extracts subdomains via regex | | `spider` | No | HTML link crawler — follows `` links up to depth 2 (max 50 pages), extracts subdomains from every visited page; complements `js_scrape` | | `ptr_sweep` | No | Reverse-DNS PTR sweep on /24 blocks containing target IPs | | `vhost_probe` | No | Virtual-host brute-force via HTTP Host-header fuzzing (130+ word built-in list) |
![Screenshot](/assets/screenshot/img2.png)
## DNS Brute-force ### Recommended Wordlists | Wordlist | Size | Use case | |---|---|---| | `subdomains-top1million-5000.txt` | 5k | Fast initial scan | | `subdomains-top1million-20000.txt` | 20k | Standard bug bounty | | `subdomains-top1million-110000.txt` | 110k | Thorough enumeration | | `best-dns-wordlist.txt` (Assetnote) | ~9M | Deep pentest | # Clone SecLists git clone --depth 1 https://github.com/danielmiessler/SecLists.git # Or download a single file wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/DNS/subdomains-top1million-20000.txt # Assetnote wordlist (generated from real CT log data) wget https://wordlists-cdn.assetnote.io/data/manual/best-dns-wordlist.txt ### Custom DNS Resolvers By default the tool uses 6 built-in resolvers (Google, Cloudflare, Quad9, OpenDNS). For large-scale brute-force, supply a bigger list: # Bundled list (~30 verified public resolvers) python simplerecon.py -d target.com --brute wordlist.txt \ --resolvers config/resolvers.txt # Download a community list on-the-fly (7000+ resolvers) python simplerecon.py -d target.com --brute wordlist.txt \ --resolvers https://public-dns.info/nameservers-all.txt # With health check - filters dead resolvers before brute-force python simplerecon.py -d target.com --brute wordlist.txt \ --resolvers https://public-dns.info/nameservers-all.txt \ --check-resolvers `--resolvers` accepts: - A local file path (`config/resolvers.txt`, one IP per line, comments with `#` supported, `ip:port` format accepted) - An `http://` or `https://` URL (downloaded automatically via `httpx`) The list is deduplicated and **shuffled** automatically to distribute load across all resolvers. Other public resolver sources: - https://github.com/trickest/resolvers - https://public-dns.info/nameservers-all.txt ### Full Brute-force Example # Fast - bundled resolvers, no validation python simplerecon.py -d target.com \ --brute wordlists/top5000.txt \ --resolvers config/resolvers.txt \ --threads 20 # Thorough - community resolvers, health check, two-pass validation python simplerecon.py -d target.com \ --brute wordlists/subdomains-top1million-20000.txt \ --resolvers https://public-dns.info/nameservers-all.txt \ --check-resolvers \ --wildcard-tests 5 \ --validate-resolvers \ --threads 30 ## TLD Brute-force `--tld-brute` discovers live registrations of the target domain under other TLDs (e.g. `target.net`, `target.io`, `target.com.br`). Useful for brand protection, typosquatting detection, and mapping the full domain portfolio of a target. # Use the built-in wordlist (~250 TLDs) python simplerecon.py -d target.com --tld-brute # Use a custom TLD list python simplerecon.py -d target.com --tld-brute custom_tlds.txt # Combine with passive enumeration and live verification python simplerecon.py -d target.com --tld-brute --verify-live -o json --outfile results.json The tool strips the current TLD from the target (handling compound TLDs like `.co.uk` and `.com.br` automatically), then resolves `{base}.{tld}` for every entry in the wordlist. Only variants that resolve in DNS are returned. Results appear in a separate `tld_variants` field in JSON/CSV/NDJSON output and are printed to the terminal at the end of each run. The default wordlist is [config/tlds.txt](config/tlds.txt). Edit it or supply your own file with `--tld-brute FILE`. ## Advanced Techniques ### Multi-probe Wildcard Detection (PureDNS) Instead of a single random-subdomain probe (unreliable under DNS load balancing), the tool fires `--wildcard-tests N` probes and confirms wildcard only when ≥ ceil(N/2) resolve. The **union of all returned IPs** is used as the filter set during brute-force. python simplerecon.py -d target.com --brute wordlist.txt --wildcard-tests 5 ### Two-pass Trusted Resolver Validation (PureDNS) After mass brute-force with cheap public resolvers, re-validate against Google/Cloudflare only. Eliminates false positives from DNS poisoning on untrusted resolvers. python simplerecon.py -d target.com --brute wordlist.txt --validate-resolvers ### TLS Certificate SAN Extraction (Amass) During `--verify-live`, the tool performs a raw SSL handshake on port 443 and extracts **Subject Alternative Names** from the server certificate. Newly discovered hostnames are added back to the subdomain set. python simplerecon.py -d target.com --verify-live --output json --outfile out.json # JSON output includes "tls_sans": ["cdn.target.com", "api.target.com", ...] per live host ### DNSSEC NSEC Zone Walking (Amass) NSEC records form a sorted linked list of every name in the DNS zone. The `nsec_walk` source traverses the chain to enumerate the entire zone without a zone transfer. Works only when the domain uses **NSEC** (not NSEC3 - the module detects and reports this automatically). python simplerecon.py -d target.com --sources nsec_walk -v # Example domain with NSEC: nlnetlabs.nl ### SRV Record Enumeration (Amass) Queries ~70 common SRV prefixes (`_http._tcp`, `_ldap._tcp`, `_kerberos._tcp`, `_autodiscover._tcp`, `_sip._tcp`, etc.). SRV records frequently reveal internal hostnames not found through passive sources. python simplerecon.py -d target.com --sources srv_enum -v The prefix list is in `config/srv_prefixes.json` - edit it to add domain-specific services. ### Recursive Enumeration (Subfinder) After enumerating `target.com`, discovered subdomains like `api.target.com` are themselves used as enumeration targets to find deeper entries (`v2.api.target.com`, `internal.api.target.com`, etc.). python simplerecon.py -d target.com --recursive --recursive-depth 2 ### GitHub Code Search Searches GitHub for source code files containing references to the target domain (hardcoded subdomains in configs, `.env` files, CI scripts). Requires a `github_token` in `config/api_keys.json`. python simplerecon.py -d target.com --sources github -v ## Subdomain Takeover Detection When `--verify-live` is enabled, each live host is checked for takeover signals via **three independent methods**: | Method | How | Field | |---|---|---| | Body fingerprint | Response body matched against ~30 service signatures | `takeover` | | CNAME chain | Full CNAME chain walked; suffix matched against 21 services | `takeover: "cname:"` | | WAF / CDN | Response headers fingerprinted against 11 providers | `waf` | python simplerecon.py -d target.com --verify-live -o json --outfile out.json [LIVE] orphan.target.com → 404 - NoSuchBucket [TAKEOVER? aws-s3] [LIVE] docs.target.com → 404 - There isn't a GitHub Pages site here. [TAKEOVER? cname:github-pages] [LIVE] api.target.com → 200 - API Gateway [cloudflare] **Takeover-detectable services (body + CNAME):** `aws-s3`, `github-pages`, `heroku`, `netlify`, `fastly`, `shopify`, `ghost-io`, `surge-sh`, `zendesk`, `readme-io`, `unbounce`, `webflow`, `squarespace`, `hubspot`, `freshdesk`, `sendgrid`, `uservoice`, `wpengine`, `pantheon`, `teamwork`, `acquia`, `bigcartel` **WAF / CDN fingerprinting:** `cloudflare`, `akamai`, `fastly`, `cloudfront`, `incapsula`, `sucuri`, `azure-cdn`, `google`, `imperva`, `barracuda`, `f5-big-ip` All fingerprints are defined in [verify/live_check.py](verify/live_check.py) (`_TAKEOVER_CNAME`, `_TAKEOVER_BODY`, `_WAF_HEADERS`) - edit there to add new services. ### jq recipes for takeover triage python simplerecon.py -d target.com --verify-live -o ndjson \ | jq 'select(.takeover != null)' # Only CNAME-based hits python simplerecon.py -d target.com --verify-live -o ndjson \ | jq 'select(.takeover | strings | startswith("cname:"))' # Show WAF-protected hosts python simplerecon.py -d target.com --verify-live -o ndjson \ | jq 'select(.waf != null) | {subdomain, waf, status}' # JSON outfile - extract takeover candidates jq -r '.live_hosts | to_entries[] | select(.value.takeover != null) | .key' out.json \ | dnsx -silent -cname -resp ## Output Formats ### Terminal (default) ------------------------------------------------------------ [*] Enumerating: target.com ------------------------------------------------------------ [*] Running passive sources... [*] [crtsh] +42 subdomains [*] [github] +8 subdomains [*] [chaos] +12 subdomains [*] [nsec_walk] +31 subdomains [*] [srv_enum] +3 subdomains [+] Total unique subdomains found: 72 api.target.com dev.target.com mail.target.com ... ### JSON python simplerecon.py -d target.com --verify-live -o json --outfile results/target.json { "domain": "target.com", "timestamp": "2026-05-27T14:32:01.123456", "total": 72, "subdomains": [ "api.target.com", "dev.target.com", "mail.target.com" ], "live_hosts": { "api.target.com": { "status": 200, "title": "API Gateway", "server": "nginx/1.24.0", "content_length": 1842, "url": "https://api.target.com", "tls_sans": ["api.target.com", "*.api.target.com", "cdn.target.com"], "cname": null, "waf": "cloudflare", "takeover": null }, "orphan.target.com": { "status": 404, "title": "", "server": "AmazonS3", "content_length": 320, "url": "https://orphan.target.com", "tls_sans": [], "cname": "orphan.target.com.s3-website-us-east-1.amazonaws.com", "waf": null, "takeover": "cname:aws-s3" } }, "sources": { "crtsh": 42, "github": 8, "chaos": 12, "nsec_walk": 31, "srv_enum": 3, "tls_sans": 5 } } ### CSV python simplerecon.py -d target.com --verify-live -o csv --outfile results/target.csv domain,subdomain,status,title,server,tls_sans,takeover,cname,waf target.com,api.target.com,200,API Gateway,nginx/1.24.0,api.target.com|*.api.target.com,,,cloudflare target.com,mail.target.com,200,Webmail,Apache/2.4,,, target.com,orphan.target.com,404,,AmazonS3,,cname:aws-s3,orphan.target.com.s3-website-us-east-1.amazonaws.com, ### NDJSON One compact JSON line per subdomain - designed for streaming and `jq` piping. python simplerecon.py -d target.com --verify-live -o ndjson python simplerecon.py -d target.com --verify-live -o ndjson --outfile results/target.ndjson {"domain": "target.com", "subdomain": "api.target.com", "status": 200, "title": "API Gateway", "server": "nginx/1.24.0", "waf": "cloudflare"} {"domain": "target.com", "subdomain": "orphan.target.com", "status": 404, "server": "AmazonS3", "cname": "orphan.target.com.s3-website-us-east-1.amazonaws.com", "takeover": "cname:aws-s3"} {"domain": "target.com", "subdomain": "dev.target.com"} **jq examples:** # Live hosts only python simplerecon.py -d target.com --verify-live -o ndjson | jq 'select(.status != null)' # Takeover candidates python simplerecon.py -d target.com --verify-live -o ndjson | jq 'select(.takeover != null)' # WAF-protected hosts python simplerecon.py -d target.com --verify-live -o ndjson | jq 'select(.waf != null) | {subdomain, waf}' # Extract only subdomains (pipe-friendly) python simplerecon.py -d target.com -o ndjson | jq -r '.subdomain' ### TXT python simplerecon.py -d target.com -o txt --outfile results/target.txt ## Advanced Usage ### Custom User-Agent python simplerecon.py -d target.com --user-agent 'Mozilla/5.0 (compatible; MyScanner/1.0)' ### Excluding sources # Run everything except noisy/slow sources python simplerecon.py -d target.com --exclude github,intelx,publicwww # Profile with overrides python simplerecon.py -d target.com --profile osint --exclude merklemap,chaos ### Stdin / pipe targets # Explicit flag echo 'target.com' | python simplerecon.py --stdin -o ndjson # Auto-detected when stdin is not a TTY cat domains.txt | python simplerecon.py -o txt # Chain with amass, subfinder, or other tools subfinder -silent -d target.com | python simplerecon.py --stdin --sources crtsh,virustotal ### httpx - HTTP probing python simplerecon.py -d target.com --no-banner | httpx -silent -status-code -title -tech-detect # Filter only 200 OK python simplerecon.py -d target.com --no-banner | httpx -silent -mc 200 ### nmap - port scan python simplerecon.py -d target.com -o txt --outfile subs.txt nmap -iL subs.txt -p 80,443,8080,8443 -T4 --open ### nuclei - vulnerability scanning python simplerecon.py -d target.com --no-banner \ | httpx -silent \ | nuclei -t cves/ -silent ### dnsx - DNS resolution and CNAME chasing # Find potential subdomain takeovers python simplerecon.py -d target.com --no-banner \ | dnsx -silent -cname -resp \ | grep -E 'amazonaws|azurewebsites|github.io|herokuapp' ### eyewitness - screenshots python simplerecon.py -d target.com --verify-live -o txt --outfile subs.txt eyewitness --web -f subs.txt --no-prompt -d screenshots/ ### SimpleReconSubdomain - enrichment and automation [SimpleReconSubdomain](https://github.com/MrCl0wnLab/SimpleReconSubdomain) (`String-x (aka strx)`) is a modular automation tool using a `{STRING}` placeholder. It pairs naturally with SimpleReconSubdomain via pipes. # HTTP probe all discovered subdomains python simplerecon.py -d target.com --no-banner \ | strx -st "echo {STRING}" -module "clc:http_probe" -pm # Resolve subdomains → extract IPs → Shodan lookup per IP python simplerecon.py -d target.com --no-banner \ | strx -st "echo {STRING}" -module "clc:dns" -pm \ | strx -st "echo {STRING}" -module "ext:ip" -pm \ | strx -st "echo {STRING}" -module "clc:shodan" -pm # Enrich with DNS + geolocation in a single chain python simplerecon.py -d target.com --no-banner \ | strx -st "echo {STRING}" -module "clc:dns|ext:ip|clc:geoip" -pm # Send live subdomains to Telegram python simplerecon.py -d target.com --no-banner \ | strx -st "echo {STRING}" -module "con:telegram" -pm ## Creating a New Module All sources inherit from `BaseSource` in `sources/base.py`. Drop the file in `sources/passive/` or `sources/active/` - no other file needs editing. The class name must be the **title-cased filename** (e.g. `myservice.py` → class `Myservice`), and `NAME` must equal the filename without `.py`. ### New Passive Source # sources/passive/myservice.py import httpx from sources.base import BaseSource from core.config import get_key class Myservice(BaseSource): NAME = 'myservice' DESCRIPTION = 'My custom service' API_TOKEN_IS_REQUIREMENT = True async def fetch(self, domain: str) -> set[str]: api_key = get_key('myservice') if not api_key: return set() subdomains: set[str] = set() async with httpx.AsyncClient(timeout=self.timeout) as client: resp = await self._get(client, f'https://api.myservice.com/subdomains/{domain}') if resp.status_code == 200: for entry in resp.json().get('data', []): subdomains.add(entry['hostname']) return self._filter(subdomains, domain) Add the key to `config/api_keys.json`: { "myservice": "your-api-key-here" } ### New Active Source Use `asyncio.wait_for` + `run_in_executor` for blocking DNS calls to prevent hangs: # sources/active/myactive.py import asyncio from sources.base import BaseSource class Myactive(BaseSource): NAME = 'myactive' DESCRIPTION = 'Active: custom DNS probe' API_TOKEN_IS_REQUIREMENT = False async def fetch(self, domain: str) -> set[str]: loop = asyncio.get_event_loop() try: return await asyncio.wait_for( loop.run_in_executor(None, self._run, domain), timeout=max(self.timeout, 30), ) except asyncio.TimeoutError: self._vlog(1, 'timed out') return set() def _run(self, domain: str) -> set[str]: subdomains: set[str] = set() try: import dns.resolver # ... blocking dnspython calls here ... except Exception as exc: self._log_exc(exc) return self._filter(subdomains, domain) ## 📄 LICENÇA Este projeto está licenciado sob a Licença Apache - veja o arquivo [LICENSE](LICENSE) para detalhes. ## 👨‍💻 AUTOR **MrCl0wn** - 🌐 **Blog**: [http://blog.mrcl0wn.com](http://blog.mrcl0wn.com) - 🐙 **GitHub**: [@MrCl0wnLab](https://github.com/MrCl0wnLab) - 🐦 **Twitter**: [@MrCl0wnLab](https://twitter.com/MrCl0wnLab) - 📧 **Email**: mrcl0wnlab\@\gmail.com
**⭐ Se este projeto foi útil, considere dar uma estrela!** **💡 Sugestões e feedbacks são sempre bem-vindos!** **💀 Hacker Hackeia!**