Windows Discovery with PowerShell
#Paste-Ready Native Discovery Script
This script accepts explicit IP addresses or hostnames. It performs bounded TCP connection checks, DNS resolution, HTTP header collection, printer-service discovery, and local wireless inventory without downloading tools or changing system configuration.
param(
[Parameter(Mandatory)]
[ValidateScript({ Test-Path -LiteralPath $_ -PathType Leaf })]
[string]$TargetsFile,
[int[]]$Ports = @(53, 80, 88, 135, 139, 389, 443, 445, 515, 631, 9100),
[ValidateRange(100, 10000)]
[int]$TimeoutMs = 1500,
[string]$OutputRoot = (Join-Path $PWD "windows-discovery")
)
$ErrorActionPreference = "Stop"
$stamp = (Get-Date).ToUniversalTime().ToString("yyyyMMddTHHmmssZ")
$output = Join-Path $OutputRoot $stamp
New-Item -ItemType Directory -Path $output -Force | Out-Null
$targets = Get-Content -LiteralPath $TargetsFile |
ForEach-Object { ($_ -split '#', 2)[0].Trim() } |
Where-Object { $_ } |
Sort-Object -Unique
if (-not $targets) {
throw "No explicit targets were supplied."
}
$results = foreach ($target in $targets) {
$addresses = try {
[System.Net.Dns]::GetHostAddresses($target).IPAddressToString -join ","
} catch {
""
}
foreach ($port in $Ports) {
$client = [System.Net.Sockets.TcpClient]::new()
try {
$task = $client.ConnectAsync($target, $port)
$open = $task.Wait($TimeoutMs) -and $client.Connected
[pscustomobject]@{
Target = $target
Addresses = $addresses
Port = $port
Open = $open
CheckedAt = (Get-Date).ToUniversalTime().ToString("o")
}
} finally {
$client.Dispose()
}
}
}
$results | Export-Csv -NoTypeInformation -LiteralPath (Join-Path $output "tcp-services.csv")
$results | Where-Object { $_.Open -and $_.Port -in 80,443 } | ForEach-Object {
$scheme = if ($_.Port -eq 443) { "https" } else { "http" }
$uri = "${scheme}://$($_.Target):$($_.Port)/"
try {
$request = @{
Uri = $uri
Method = "Head"
TimeoutSec = 5
}
if ($PSVersionTable.PSVersion.Major -ge 7) {
$request.SkipCertificateCheck = $true
}
$response = Invoke-WebRequest @request
[pscustomobject]@{
Uri = $uri
StatusCode = [int]$response.StatusCode
Server = $response.Headers.Server
}
} catch {
[pscustomobject]@{ Uri = $uri; StatusCode = ""; Server = ""; Error = $_.Exception.Message }
}
} | Export-Csv -NoTypeInformation -LiteralPath (Join-Path $output "http-head.csv")
Get-Printer -ErrorAction SilentlyContinue |
Select-Object Name, ComputerName, PortName, DriverName, Type, Shared |
Export-Csv -NoTypeInformation -LiteralPath (Join-Path $output "local-printers.csv")
netsh wlan show interfaces | Out-File -LiteralPath (Join-Path $output "wireless-interfaces.txt")
netsh wlan show networks mode=bssid | Out-File -LiteralPath (Join-Path $output "wireless-networks.txt")
Get-ChildItem -LiteralPath $output -File |
Get-FileHash -Algorithm SHA256 |
Export-Csv -NoTypeInformation -LiteralPath (Join-Path $output "manifest.csv")
Write-Host "Discovery output: $output"
POWERSHELL
On PowerShell 5.1, certificate failures are recorded rather than bypassed. PowerShell 7 can collect headers from devices with self-signed certificates without changing global certificate validation.