Skip to content

Instantly share code, notes, and snippets.

@chaddoncooper
Created March 17, 2026 12:07
Show Gist options
  • Select an option

  • Save chaddoncooper/61598727bf77c566dd946cdcdb7ce006 to your computer and use it in GitHub Desktop.

Select an option

Save chaddoncooper/61598727bf77c566dd946cdcdb7ce006 to your computer and use it in GitHub Desktop.
#Requires -Version 5.1
param(
[string]$Domain = '',
[switch]$Json,
[switch]$Silent,
[switch]$Help
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
function Die {
param([string]$Message)
Write-Error "Fatal: $Message" -ErrorAction Stop
}
function Test-CommandAvailable {
param([string]$Command)
$cmd = Get-Command $Command -ErrorAction SilentlyContinue
if ($null -eq $cmd) { return $false }
return $true
}
function Show-Help {
@"
Subdomains (Native PowerShell Probing)
Usage:
.\Lookup-SubDomains.ps1 [-Json] [-Silent] -Domain <domain>
.\Lookup-SubDomains.ps1 -Help
"@
}
function Assert-Dependencies {
$deps = @('curl.exe', 'jq')
foreach ($dep in $deps) {
if (-not (Test-CommandAvailable $dep)) {
Die "Missing '$dep' dependency. Please ensure curl and jq are in your PATH."
}
}
}
function Main {
if ($Help) { Show-Help; exit 0 }
Assert-Dependencies
if ([string]::IsNullOrWhiteSpace($Domain)) {
Die "No domain provided. Use -Domain 'example.com'."
}
$timestamp = [DateTimeOffset]::UtcNow.ToUnixTimeSeconds()
$resultDir = Join-Path $HOME ".cache/subdomains/${timestamp}-${Domain}"
New-Item -ItemType Directory -Path $resultDir -Force | Out-Null
$crtAll = Join-Path $resultDir "crt-all.txt"
$crtUniq = Join-Path $resultDir "crt-uniq.txt"
$aliveFile = Join-Path $resultDir "alive.txt"
if (-not $Silent) { Write-Host " [+] Fetching subdomains from crt.sh..." }
# Fetch and process
try {
curl.exe --silent "https://crt.sh/?q=${Domain}&output=json" |
jq '.[].name_value' |
ForEach-Object { $_ -replace '"', '' } |
ForEach-Object { $_ -split "`n" } |
ForEach-Object { $_.Trim() } |
Where-Object { $_ -ne '' } |
Set-Content $crtAll
}
catch {
Die "Failed to fetch or parse data from crt.sh."
}
# Verify if we actually found anything
if (-not (Test-Path $crtAll) -or (Get-Item $crtAll).Length -eq 0) {
if (-not $Silent) { Write-Host " [!] No subdomains found for $Domain." -ForegroundColor Yellow }
exit 0
}
if (-not $Silent) { Write-Host " [+] Cleaning list..." }
Get-Content $crtAll | Sort-Object -Unique | Where-Object { $_ -notmatch '\*' } | Set-Content $crtUniq
if (-not $Silent) { Write-Host " [+] Probing for alive domains..." }
# Check if the unique file exists before reading
if (Test-Path $crtUniq) {
$uniqueDomains = Get-Content $crtUniq
$aliveResults = New-Object System.Collections.Generic.List[string]
foreach ($d in $uniqueDomains) {
foreach ($proto in @("https://", "http://")) {
try {
$url = "$proto$d"
# -UseBasicParsing prevents IE engine issues in PS 5.1
$null = Invoke-WebRequest -Uri $url -Method Head -TimeoutSec 2 -ErrorAction Stop -UseBasicParsing
if (-not $Silent) { Write-Host " [OK] $url" -ForegroundColor Green }
$aliveResults.Add($d)
break
}
catch { continue }
}
}
$aliveResults | Sort-Object -Unique | Set-Content $aliveFile
}
# Output results
if (Test-Path $aliveFile) {
$finalCount = (Get-Content $aliveFile).Count
if (-not $Silent) { Write-Host " [+] Found $finalCount alive domains. Results in $resultDir" }
if ($Json) {
Get-Content $aliveFile | ConvertTo-Json
}
elseif (-not $Silent) {
Get-Content $aliveFile
}
}
else {
if (-not $Silent) { Write-Host " [-] No alive domains responded." -ForegroundColor Red }
}
}
Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment