Public/Reconnaissance/anonymous/Find-DnsRecords.ps1
using namespace System.Management.Automation class SubdomainCategories : IValidateSetValuesGenerator { [string[]] GetValidValues() { $categories = @('all') if ($script:SessionVariables -and $script:SessionVariables.subdomains -and $script:SessionVariables.subdomains.default) { $categories += $script:SessionVariables.subdomains.default.Keys } return $categories } } function Find-DnsRecords { [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [Alias("d", "domain")] [string[]]$Domains, [Parameter(Mandatory = $false)] [ValidateRange(1, 300)] [Alias("delay-min", "min-delay")] [int]$MinDelay = 1, [Parameter(Mandatory = $false)] [ValidateRange(1, 600)] [Alias("delay-max", "max-delay")] [int]$MaxDelay = 3, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [Alias("log-path", "l", "log")] [string]$LogPath = ".\recon_results.log", [Parameter(Mandatory = $false)] [ValidateSet("A", "AAAA", "CNAME", "MX", "NS", "TXT", "SOA", "PTR")] [Alias("record-types", "types", "r")] [string[]]$RecordTypes = @("A", "AAAA", "CNAME", "MX", "TXT"), [Parameter(Mandatory = $false)] [Alias("fast", "f")] [switch]$FastMode, [Parameter(Mandatory = $false)] [ValidateSet("Minimal", "Standard", "Detailed")] [Alias("info-level", "level")] [string]$DNSInfoLevel = "Standard", [Parameter(Mandatory = $false)] [ValidateSet("Object", "JSON", "CSV", "Table")] [Alias("output", "o")] [string]$OutputFormat = "Table", [Parameter(Mandatory = $false)] [Alias("no-cache", "bypass-cache")] [switch]$SkipCache, [Parameter(Mandatory = $false)] [Alias("cache-expiration", "expiration")] [int]$CacheExpirationMinutes = 30, [Parameter(Mandatory = $false)] [Alias("max-cache")] [int]$MaxCacheSize = 100, [Parameter(Mandatory = $false)] [Alias("compress")] [switch]$CompressCache, [Parameter(Mandatory = $false)] [Alias("enum-subdomains", "subdomains", "s")] [switch]$EnumerateSubdomains, [Parameter(Mandatory = $false)] [ValidateRange(1, 200)] [Alias("subdomain-throttle", "throttle-limit", "t")] [int]$SubdomainThrottleLimit = 50, [Parameter(Mandatory = $false)] [ValidateSet([SubdomainCategories])] [Alias("subdomain-cat", "cat", "c")] [string]$SubdomainCategory = "common", [Parameter(Mandatory = $false)] [Alias("deep-search", "deep", "ds")] [switch]$DeepSubdomainSearch ) begin { Write-Verbose "Starting DNS reconnaissance with enhanced provider support" if ($MinDelay -gt $MaxDelay) { throw "MinDelay cannot be greater than MaxDelay" } if ($EnumerateSubdomains -and $SubdomainThrottleLimit -gt 200) { Write-Warning "High subdomain throttle limit may cause rate limiting. Consider reducing to 100 or less." } if ($DeepSubdomainSearch -and -not $EnumerateSubdomains) { Write-Warning "DeepSubdomainSearch requires EnumerateSubdomains to be enabled. Enabling subdomain enumeration." $EnumerateSubdomains = $true } $MyInvocation.MyCommand.Name | Invoke-BlackCat -ResourceTypeName 'DnsRecon' $DNSProviders = @{ "Cloudflare" = @{ URL = "https://cloudflare-dns.com/dns-query"; Region = "Global"; Type = "Commercial"; Reliability = 99.9 } "Google" = @{ URL = "https://dns.google/resolve"; Region = "Global"; Type = "Commercial"; Reliability = 99.8 } "NextDNS" = @{ URL = "https://dns.nextdns.io"; Region = "Global"; Type = "Privacy"; Reliability = 99.5 } "DNS.SB" = @{ URL = "https://doh.dns.sb/dns-query"; Region = "Global"; Type = "Privacy"; Reliability = 99.3 } "DNSPod" = @{ URL = "https://dns.pub/dns-query"; Region = "China/Global"; Type = "Commercial"; Reliability = 99.0 } } # User agents - integrate with BlackCat module if available (replaces UseRandomUserAgent parameter) if ($BlackCatAvailable -and $script:SessionVariables -and $script:SessionVariables.userAgents) { Write-Verbose "Using BlackCat module user agents from session variables" $UserAgents = $script:SessionVariables.userAgents.agents | ForEach-Object { $_.value } } else { Write-Verbose "Using built-in user agents (anonymous mode)" $UserAgents = @( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_5_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0" ) } # Initialize results and configuration $Results = [System.Collections.ArrayList]::new() $Stats = @{ TotalQueries = 0; SuccessfulQueries = 0; FailedQueries = 0; StartTime = Get-Date } $Config = @{ MinDelay = if ($FastMode) { 0.5 } else { $MinDelay } MaxDelay = if ($FastMode) { 1 } else { $MaxDelay } Timeout = if ($FastMode) { 2 } else { 10 } } } process { foreach ($Domain in $Domains) { # Generate a cache key for the current domain and parameters $cacheParams = @{ Domain = $Domain RecordTypes = ($RecordTypes -join ",") EnumerateSubdomains = $EnumerateSubdomains.IsPresent DeepSubdomainSearch = $DeepSubdomainSearch.IsPresent SubdomainCategory = $SubdomainCategory } $cacheKey = ConvertTo-CacheKey -BaseIdentifier "Find-DnsRecords" -Parameters $cacheParams # Try to get cached results if not skipping cache if (-not $SkipCache) { try { $cachedResult = Get-BlackCatCache -Key $cacheKey -CacheType 'General' if ($null -ne $cachedResult) { Write-Verbose "Retrieved DNS results from cache for domain: $Domain" # Merge cached results into Results collection foreach ($entry in $cachedResult) { [void]$Results.Add($entry) } # Skip processing this domain since we have cached results continue } } catch { Write-Verbose "Error retrieving from cache: $($_.Exception.Message). Proceeding with fresh DNS queries." } } Write-Host "🎯 Analyzing domain: $Domain" -ForegroundColor Green # Rotate through providers for load balancing $ProviderNames = $DNSProviders.Keys | Sort-Object { Get-Random } # Build list of domains to query (root domain + subdomains if enabled) $DomainsToQuery = @($Domain) # Add subdomain enumeration for CNAME discovery if ($EnumerateSubdomains -and $RecordTypes -contains "CNAME") { Write-Host " 🔍 Enumerating subdomains for CNAME discovery..." -ForegroundColor Cyan # Determine subdomain type based on DeepSubdomainSearch parameter $SubdomainType = if ($DeepSubdomainSearch) { 'deep' } else { 'default' } # Get subdomain list from session variables (same logic as Find-SubDomain) $SubdomainList = if ($script:SessionVariables -and $script:SessionVariables.subdomains) { Write-Verbose "Using session variable subdomain list (type: $SubdomainType, category: $SubdomainCategory)" $subdomains = [System.Collections.Generic.HashSet[string]]::new() if ($SubdomainCategory -eq 'all') { foreach ($cat in $script:SessionVariables.subdomains[$SubdomainType].Keys) { # Skip the 'common' category when 'all' is selected for improved performance if ($cat -ne 'common') { foreach ($sd in $script:SessionVariables.subdomains[$SubdomainType].$cat) { [void]$subdomains.Add($sd) } } } } else { if ($script:SessionVariables.subdomains[$SubdomainType].ContainsKey($SubdomainCategory)) { foreach ($sd in $script:SessionVariables.subdomains[$SubdomainType].$SubdomainCategory) { [void]$subdomains.Add($sd) } } else { Write-Warning "Category '$SubdomainCategory' not found in session variables. Available categories: $($script:SessionVariables.subdomains[$SubdomainType].Keys -join ', ')" $subdomains = $null } } if ($subdomains) { [array]$subdomains } else { $null } } else { Write-Warning "Session variables not available. Cannot enumerate subdomains without BlackCat framework." $null } if (-not $SubdomainList) { Write-Host " ⚠️ Subdomain enumeration skipped - no subdomain data available" -ForegroundColor Yellow continue } # Generate subdomain candidates $SubdomainCandidates = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) foreach ($subdomain in $SubdomainList) { [void]$SubdomainCandidates.Add("$subdomain.$Domain") } $SearchTypeMsg = if ($DeepSubdomainSearch) { "deep search" } else { "standard search" } Write-Host " 🎯 Testing $($SubdomainCandidates.Count) subdomain candidates ($SearchTypeMsg, category: $SubdomainCategory)..." -ForegroundColor Yellow # Test subdomains in parallel for existence first (faster DNS resolution check) $ValidSubdomains = $SubdomainCandidates | ForEach-Object -Parallel { try { $null = [System.Net.Dns]::GetHostEntry($_) return $_ } catch { # Subdomain doesn't resolve, skip it return $null } } -ThrottleLimit $SubdomainThrottleLimit | Where-Object { $_ -ne $null } $DomainsToQuery += $ValidSubdomains Write-Host " ✅ Found $($ValidSubdomains.Count) valid subdomains" -ForegroundColor Green } foreach ($RecordType in $RecordTypes) { Write-Host " 🔍 Querying $RecordType records..." -ForegroundColor Yellow # Query each domain (root + valid subdomains) foreach ($QueryDomain in $DomainsToQuery) { # Skip subdomain enumeration for non-CNAME record types on subdomains if ($QueryDomain -ne $Domain -and $RecordType -ne "CNAME") { continue } if ($DNSInfoLevel -eq "Detailed" -and $QueryDomain -ne $Domain) { Write-Host " 🔍 Querying $RecordType for subdomain: $QueryDomain" -ForegroundColor Gray } foreach ($ProviderName in $ProviderNames) { $Provider = $DNSProviders[$ProviderName] if ($DNSInfoLevel -eq "Detailed") { Write-Host " 📡 Using $ProviderName ($($Provider.Reliability)%)" -ForegroundColor Cyan } try { $Stats.TotalQueries++ # JSON DNS query $QueryUrl = "$($Provider.URL)?name=$QueryDomain&type=$RecordType" $Headers = @{ "Accept" = "application/dns-json" "User-Agent" = ($UserAgents | Get-Random) } $Response = Invoke-RestMethod -Uri $QueryUrl -Headers $Headers -TimeoutSec $Config.Timeout -ErrorAction Stop # Debug output for CNAME queries if ($DNSInfoLevel -eq "Detailed" -and $RecordType -eq "CNAME") { Write-Host " 🔍 Query URL: $QueryUrl" -ForegroundColor Gray Write-Host " 🔍 Response has $($Response.Answer.Count) answers" -ForegroundColor Gray } # ... existing code for processing Response.Answer ... # For CNAME queries, also try with DO (DNSSEC OK) bit to get unfiltered responses if ($RecordType -eq "CNAME" -and -not $Response.Answer) { try { $DnssecQueryUrl = "$($Provider.URL)?name=$QueryDomain&type=$RecordType&do=true" $DnssecResponse = Invoke-RestMethod -Uri $DnssecQueryUrl -Headers $Headers -TimeoutSec $Config.Timeout -ErrorAction Stop if ($DnssecResponse.Answer) { $Response = $DnssecResponse if ($DNSInfoLevel -eq "Detailed") { Write-Host " 🔍 DNSSEC query returned $($Response.Answer.Count) answers" -ForegroundColor Gray } } } catch { # DNSSEC query failed, continue with original response if ($DNSInfoLevel -eq "Detailed") { Write-Host " 🔍 DNSSEC query failed: $($_.Exception.Message)" -ForegroundColor Gray } } # If still no CNAME found, try querying for A records to detect proxied CNAMEs if (-not $Response.Answer) { try { $AQueryUrl = "$($Provider.URL)?name=$QueryDomain&type=A" $AResponse = Invoke-RestMethod -Uri $AQueryUrl -Headers $Headers -TimeoutSec $Config.Timeout -ErrorAction Stop if ($AResponse.Answer) { # Check if the A records point to CDN IPs (indicating CNAME flattening/proxying) $CDNRecords = $AResponse.Answer | Where-Object { $_.type -eq 1 -and ( # Cloudflare IP ranges (more comprehensive) ($_.data -match '^(104\.1[6-9]|104\.2[0-7]|104\.21|104\.22|104\.23|104\.24|104\.25|104\.26|104\.27|104\.28|104\.29|104\.30|104\.31|108\.162|141\.101|162\.15[8-9]|172\.6[4-7]|172\.64|172\.65|172\.66|172\.67|172\.68|172\.69|172\.70|172\.71|173\.245|188\.114|190\.93|197\.234|198\.41|131\.0|203\.28)\.') -or # AWS CloudFront ($_.data -match '^(13\.32|13\.35|52\.8[4-5]|54\.23[0-9]|99\.8[4-6]|143\.204|205\.251)\.') -or # Fastly ($_.data -match '^(23\.235|151\.101)\.') -or # KeyCDN ($_.data -match '^(95\.85|104\.16)\.') -or # MaxCDN/StackPath ($_.data -match '^(66\.254|68\.232)\.') ) } if ($CDNRecords) { $Response = $AResponse if ($DNSInfoLevel -eq "Detailed") { Write-Host " 🔍 A record query returned $($CDNRecords.Count) CDN records (likely flattened CNAME)" -ForegroundColor Gray } } } } catch { if ($DNSInfoLevel -eq "Detailed") { Write-Host " 🔍 A record fallback query failed: $($_.Exception.Message)" -ForegroundColor Gray } } } } if ($Response.Answer) { $FoundRecord = $false foreach ($Answer in $Response.Answer) { # More flexible record type matching - check both by type number and handle edge cases $ExpectedType = (@{"A"=1;"AAAA"=28;"CNAME"=5;"MX"=15;"NS"=2;"TXT"=16;"SOA"=6;"PTR"=12}[$RecordType]) # Debug output for CNAME queries when in detailed mode if ($DNSInfoLevel -eq "Detailed" -and $RecordType -eq "CNAME") { Write-Host " 🔍 Answer type: $($Answer.type), Expected: $ExpectedType, Data: $($Answer.data)" -ForegroundColor Gray } # For CNAME queries, check if this is actually a CNAME record if ($RecordType -eq "CNAME" -and $Answer.type -eq 5) { $null = $Results.Add([PSCustomObject]@{ Domain = $QueryDomain RecordType = $RecordType Data = $Answer.data TTL = $Answer.TTL DNSProvider = $ProviderName ProviderType = $Provider.Type ProviderRegion = $Provider.Region Reliability = $Provider.Reliability Timestamp = Get-Date QueryMethod = "DoH-JSON" IsSubdomain = ($QueryDomain -ne $Domain) }) $Stats.SuccessfulQueries++ $DisplayDomain = if ($QueryDomain -ne $Domain) { $QueryDomain } else { $QueryDomain } Write-Host " ✅ $DisplayDomain -> $($Answer.data) (TTL: $($Answer.TTL))" -ForegroundColor Green $FoundRecord = $true } # For non-CNAME queries or exact type matches elseif ($Answer.type -eq $ExpectedType) { $null = $Results.Add([PSCustomObject]@{ Domain = $QueryDomain RecordType = $RecordType Data = $Answer.data TTL = $Answer.TTL DNSProvider = $ProviderName ProviderType = $Provider.Type ProviderRegion = $Provider.Region Reliability = $Provider.Reliability Timestamp = Get-Date QueryMethod = "DoH-JSON" IsSubdomain = ($QueryDomain -ne $Domain) }) $Stats.SuccessfulQueries++ $DisplayDomain = if ($QueryDomain -ne $Domain) { $QueryDomain } else { $QueryDomain } Write-Host " ✅ $DisplayDomain -> $($Answer.data) (TTL: $($Answer.TTL))" -ForegroundColor Green $FoundRecord = $true } } # Special handling for CNAME queries that might be resolved to final A/AAAA records if ($RecordType -eq "CNAME" -and -not $FoundRecord) { # Check if we got A or AAAA records when querying for CNAME (indicates proxied/resolved CNAME) $ProxiedRecords = $Response.Answer | Where-Object { $_.type -eq 1 -or $_.type -eq 28 } if ($ProxiedRecords) { foreach ($ProxiedRecord in $ProxiedRecords) { # Try to detect if this is likely a proxied CNAME by checking common CDN patterns $IsLikelyProxied = $false $ProxyService = "Unknown" # Comprehensive Cloudflare IP ranges if ($ProxiedRecord.data -match '^(104\.1[6-9]|104\.2[0-7]|104\.21|104\.22|104\.23|104\.24|104\.25|104\.26|104\.27|104\.28|104\.29|104\.30|104\.31|108\.162|141\.101|162\.15[8-9]|172\.6[4-7]|172\.64|172\.65|172\.66|172\.67|172\.68|172\.69|172\.70|172\.71|173\.245|188\.114|190\.93|197\.234|198\.41|131\.0|203\.28)\.') { $IsLikelyProxied = $true $ProxyService = "Cloudflare" } # AWS CloudFront patterns elseif ($ProxiedRecord.data -match '^(13\.32|13\.35|52\.8[4-5]|54\.23[0-9]|99\.8[4-6]|143\.204|205\.251)\.') { $IsLikelyProxied = $true $ProxyService = "AWS CloudFront" } # Fastly CDN elseif ($ProxiedRecord.data -match '^(23\.235|151\.101)\.') { $IsLikelyProxied = $true $ProxyService = "Fastly" } # Common other CDN patterns can be added here if ($IsLikelyProxied) { $null = $Results.Add([PSCustomObject]@{ Domain = $QueryDomain RecordType = "CNAME (Flattened)" Data = "$($ProxiedRecord.data) [$ProxyService Flattened/Proxied]" TTL = $ProxiedRecord.TTL DNSProvider = $ProviderName ProviderType = $Provider.Type ProviderRegion = $Provider.Region Reliability = $Provider.Reliability Timestamp = Get-Date QueryMethod = "DoH-JSON" IsSubdomain = ($QueryDomain -ne $Domain) }) $Stats.SuccessfulQueries++ $DisplayDomain = if ($QueryDomain -ne $Domain) { $QueryDomain } else { $QueryDomain } Write-Host " 🔶 $DisplayDomain -> $($ProxiedRecord.data) [$ProxyService Flattened CNAME] (TTL: $($ProxiedRecord.TTL))" -ForegroundColor DarkYellow $FoundRecord = $true } } } } } else { # Handle case where no records are found if ($DNSInfoLevel -ne "Minimal" -and $QueryDomain -eq $Domain) { Write-Host " ℹ️ No $RecordType records found" -ForegroundColor Gray } } # Add delay between requests if ($Config.MaxDelay -gt 0) { $Delay = Get-Random -Minimum $Config.MinDelay -Maximum $Config.MaxDelay Start-Sleep -Seconds $Delay } # Break after successful response (whether records found or authoritative no-records) # Only continue to next provider on actual HTTP/network failures break # Success - got authoritative response from DNS provider } catch { $Stats.FailedQueries++ if ($DNSInfoLevel -eq "Detailed") { Write-Host " ❌ Query failed: $($_.Exception.Message)" -ForegroundColor Red } } } } } # Store domain-specific results in cache if (-not $SkipCache) { try { # Get only results for this domain $domainResults = $Results | Where-Object { $_.Domain -eq $Domain -or ($_.Domain -like "*.$Domain" -and $_.IsSubdomain -eq $true) } # Cache results if we have any if ($domainResults -and $domainResults.Count -gt 0) { Set-BlackCatCache -Key $cacheKey -Data $domainResults -ExpirationMinutes $CacheExpirationMinutes ` -CacheType 'General' -MaxCacheSize $MaxCacheSize -CompressData:$CompressCache Write-Verbose "Cached DNS results for domain: $Domain (expires in $CacheExpirationMinutes minutes)" } } catch { Write-Verbose "Failed to cache results for domain $Domain`: $($_.Exception.Message)" } } } } end { $Duration = (Get-Date) - $Stats.StartTime Write-Host "`n📊 Reconnaissance Summary:" -ForegroundColor Magenta Write-Host " Total Queries: $($Stats.TotalQueries)" -ForegroundColor White Write-Host " Successful: $($Stats.SuccessfulQueries)" -ForegroundColor Green Write-Host " Failed: $($Stats.FailedQueries)" -ForegroundColor Red Write-Host " Duration: $($Duration.TotalSeconds.ToString('F2')) seconds" -ForegroundColor White Write-Host " Records Found: $($Results.Count)" -ForegroundColor Yellow if ($EnumerateSubdomains) { $SubdomainResults = $Results | Where-Object { $_.IsSubdomain -eq $true } Write-Host " Subdomain Records: $($SubdomainResults.Count)" -ForegroundColor Cyan } # Format and return results using Format-BlackCatOutput if available $formatParam = @{ Data = $Results OutputFormat = $OutputFormat FunctionName = $MyInvocation.MyCommand.Name FilePrefix = 'DNSRecon' } return Format-BlackCatOutput @formatParam } <# .SYNOPSIS Performs comprehensive DNS reconnaissance on target domains with enhanced provider support and subdomain enumeration capabilities. .DESCRIPTION Find-DnsRecords is an advanced DNS reconnaissance tool that queries multiple DNS-over-HTTPS providers to gather DNS records for specified domains. It supports various record types, subdomain enumeration with CNAME discovery, and can detect flattened/proxied CNAMEs used by CDN services like Cloudflare. The function provides load balancing across multiple DNS providers, customizable delays for stealth, and integrates with the BlackCat framework for enhanced subdomain lists and user agent rotation. .PARAMETER Domains One or more target domains to perform DNS reconnaissance on. Accepts pipeline input. .PARAMETER MinDelay Minimum delay in seconds between DNS queries (1-300). Default: 1 second. Helps avoid rate limiting. .PARAMETER MaxDelay Maximum delay in seconds between DNS queries (1-600). Default: 3 seconds. Random delay between MinDelay and MaxDelay is used. .PARAMETER LogPath Path to save reconnaissance results log file. Default: ".\recon_results.log" .PARAMETER RecordTypes Array of DNS record types to query. Valid values: "A", "AAAA", "CNAME", "MX", "NS", "TXT", "SOA", "PTR" Default: @("A", "AAAA", "CNAME", "MX", "TXT") .PARAMETER FastMode Switch to enable fast mode with reduced delays and timeouts. Overrides MinDelay/MaxDelay settings. .PARAMETER DNSInfoLevel Level of detail in output messages. Valid values: "Minimal", "Standard", "Detailed" Default: "Standard" .PARAMETER OutputFormat Format for the returned results. Valid values: "Object", "JSON", "CSV", "Table" Default: "Table" .PARAMETER SkipCache Switch to bypass using cached results and force a fresh DNS query. Default: False (cache is used if available) .PARAMETER CacheExpirationMinutes Number of minutes to store results in cache before they expire. Default: 30 minutes .PARAMETER MaxCacheSize Maximum number of entries to keep in the cache (uses LRU eviction). Default: 100 entries .PARAMETER CompressCache Switch to enable compression of cached data to reduce memory usage. Default: False (no compression) .PARAMETER EnumerateSubdomains Switch to enable subdomain enumeration for CNAME discovery. Requires BlackCat framework session variables for subdomain lists. .PARAMETER SubdomainThrottleLimit Maximum number of parallel threads for subdomain testing (1-200). Default: 50. Higher values may cause rate limiting. .PARAMETER SubdomainCategory Category of subdomains to enumerate from session variables. Valid values depend on loaded subdomain lists (e.g., "common", "cloud", "all"). Default: "common" .PARAMETER DeepSubdomainSearch Switch to enable deep subdomain search using extended wordlists. Automatically enables EnumerateSubdomains if not already set. .EXAMPLE Find-DnsRecords -Domains "example.com" -RecordTypes "A","CNAME" Performs basic DNS reconnaissance for A and CNAME records on example.com. .EXAMPLE Find-DnsRecords -Domains "example.com","test.com" -EnumerateSubdomains -SubdomainCategory "cloud" -OutputFormat JSON Enumerates cloud-related subdomains for multiple domains and returns results in JSON format. .EXAMPLE @("domain1.com", "domain2.com") | Find-DnsRecords -FastMode -RecordTypes "A","AAAA","CNAME" -DNSInfoLevel Detailed Performs fast reconnaissance with detailed output for multiple domains via pipeline. .EXAMPLE Find-DnsRecords -Domains "target.com" -EnumerateSubdomains -DeepSubdomainSearch -SubdomainThrottleLimit 100 Performs deep subdomain enumeration with increased parallelization for comprehensive CNAME discovery. .EXAMPLE Find-DnsRecords -Domains "example.com" -OutputFormat JSON -OutputFile "example-dns-scan" Performs DNS reconnaissance and exports the results to "example-dns-scan.json" using Format-BlackCatOutput. .EXAMPLE Find-DnsRecords -Domains "example.com" -CacheExpirationMinutes 60 -CompressCache Performs DNS reconnaissance and caches the results for 60 minutes with compression enabled. .EXAMPLE Find-DnsRecords -Domains "example.com" -SkipCache Forces a fresh DNS lookup, bypassing any cached results for the domain. .NOTES Author: BlackCat Security Framework Version: 2.0.0 This function integrates with the BlackCat framework when available, providing: - Enhanced subdomain wordlists from session variables - Randomized user agent rotation - Category-based subdomain enumeration - CNAME flattening detection .INPUTS System.String[] Accepts domain names from pipeline. .OUTPUTS System.Object[] | System.String Returns DNS record objects in specified format (Object, JSON, CSV, or Table). .LINK https://github.com/blackcat/reconnaissance #> } |