├── PortScanner.ps1 ├── README.md ├── Resources └── service-names-port-numbers.csv └── examples.png /PortScanner.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Powershell TCP Port Scanner. 4 | 5 | .DESCRIPTION 6 | This script performs TCP port scans, providing the option to specify an entire network. 7 | 8 | .PARAMETER Hosts 9 | A hostname, an IPv4 address, or a network to be scanned. 10 | 11 | .PARAMETER Ports 12 | A TCP port, a range of ports in the form x..x, or a series of ports separated by commas. 13 | 14 | .PARAMETER Pn 15 | Optional. Disable ping for host verification before scanning. 16 | 17 | .PARAMETER n 18 | Optional. Disable dns lookup. 19 | 20 | .EXAMPLE 21 | TCP Scan providing a hostname with DSN Lookup and Ping validation. 22 | .\PortScanner.ps1 -Hosts google.com -Ports 80,443 23 | 24 | .EXAMPLE 25 | TCP Scan providing an IPv4 address with no DSN Lookup. 26 | .\PortScanner.ps1 -Hosts 192.168.88.10 -n -Ports 80 27 | 28 | .EXAMPLE 29 | TCP Scan providing a network address disabling both DNS lookup and ping verification.. 30 | .\PortScanner.ps1 -Hosts 192.168.88.0/24 -n -Pn -Ports 20..8080 31 | 32 | .NOTES 33 | Autore: Giuseppe Argento 34 | Versione: 1.0 35 | Data: 28/11/2023 36 | #> 37 | 38 | param( 39 | [CmdletBinding()] 40 | [Parameter(Mandatory=$true, Position=0)] 41 | [string]$Hosts, 42 | 43 | [Parameter(Mandatory=$true, Position=1)] 44 | [string]$Ports, 45 | 46 | [System.Management.Automation.SwitchParameter]$Pn, 47 | 48 | [System.Management.Automation.SwitchParameter]$n 49 | 50 | ) 51 | 52 | function CheckResourceFile { 53 | $PortList_Path = "$PSScriptRoot\Resources\service-names-port-numbers.csv" 54 | 55 | If(-not(Test-Path -Path $PortList_Path)){ 56 | Write-Error "Missing service-names-port-numbers.csv file." -ErrorAction Stop 57 | } 58 | 59 | $PortServices = @{} 60 | ForEach($line in Get-Content -Path $PortList_Path) { 61 | If(-not [string]::IsNullOrEmpty($line)){ 62 | Try{ 63 | $data = $line -split "," 64 | 65 | If ($data[2] -eq "tcp"){ 66 | If([string]::IsNullOrEmpty($data[0])){ 67 | $data[0] = "-" 68 | } 69 | $PortServices.Add([int]$data[1], $data[0]) 70 | } 71 | }Catch [System.ArgumentException]{} 72 | } 73 | } 74 | return $PortServices 75 | 76 | } 77 | 78 | function SendPing { 79 | param( 80 | [Parameter(Mandatory=$true)] 81 | [string]$Hostname 82 | ) 83 | 84 | Try{ 85 | $res = Test-Connection -ComputerName $Hostname -Count 1 -ErrorAction SilentlyContinue 86 | if($res.StatusCode -eq 0){ 87 | #Write-Host "$Hostname is reachable." -ForegroundColor Green 88 | return $true 89 | }else{ 90 | #Write-Host "$Hostname is unreachable." -ForegroundColor Red 91 | return $false 92 | } 93 | }Catch{ 94 | #Write-Host "$Hostname is unreachable." -ForegroundColor Red 95 | return $false 96 | } 97 | } 98 | 99 | 100 | function CalculateNetwork{ 101 | param( 102 | [Parameter(Mandatory=$true)] 103 | [string]$NetIP 104 | ) 105 | 106 | if($NetIP -match ".*/[0-9]+$"){ 107 | [int] $cidr = ($NetIP -split "/")[1] 108 | $IP = ($NetIP -split "/")[0] 109 | if ($IP -match "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"){ 110 | ##Verifying the CIDR is between 7 and 30 111 | if($cidr -ge 7 -and $cidr -le 30){ 112 | $BinaryIP = @() 113 | ##Divide IP in octects 114 | $octects = $IP -split "\." 115 | foreach($octect in $octects){ 116 | ##Convert octect in a bit sequence string 117 | $binary = [convert]::ToString($octect,2) 118 | ##Create byte rapresentation 119 | $oct_binary = '0'* (8 - $binary.Length) + $binary 120 | 121 | $BinaryIP = $BinaryIP + $oct_binary 122 | } 123 | ##Create the binary sequence of the entire IP 124 | $BinaryIP = $BinaryIP -join '' 125 | 126 | ##Number of bit for hosts part and Ids part for Network and Hosts 127 | $host_len = 32 - $cidr 128 | $NetworkID = $BinaryIP.Substring(0,$cidr) 129 | 130 | $HostID = $BinaryIP.Substring($cidr,$host_len) 131 | $HostID = $HostID -replace '1','0' 132 | 133 | #Max number of configurable IPs 134 | $max_ips = [convert]::ToInt32(('1'* $host_len),2) -1 135 | $IPs = @() 136 | 137 | For ($i = 1; $i -le $max_ips; $i++){ 138 | $HostIDdecimal = ([convert]::ToInt32($HostID, 2) + $i ) 139 | $HostIDbinary = [convert]::ToString($HostIDdecimal, 2) 140 | 141 | $NoOfZerosToAdd = $HostID.Length - $HostIDbinary.Length 142 | $HostIDbinary = ('0' * $NoOfZerosToAdd) + $HostIDbinary 143 | 144 | $NextIPbinary = $NetworkID + $HostIDbinary 145 | 146 | $IP = @() 147 | #Transform each Octect 148 | For ($x = 1; $x -le 4; $x++){ 149 | $StartCharNumber = ($x-1) * 8 150 | $IPoctectBinary = $NextIPbinary.Substring($StartCharNumber, 8) 151 | $IPoctectDecimal = [convert]::ToInt32($IPoctectBinary, 2) 152 | 153 | $IP += $IPoctectDecimal 154 | } 155 | $IP = $IP -join '.' 156 | $IPs += $IP 157 | 158 | } 159 | return $IPs 160 | #Write-Output -InputObject $Ips 161 | }else{ 162 | Write-Error "The value of CIDR is not correct" -ErrorAction Stop 163 | } 164 | }else{ 165 | Write-Error "The IP is not valid." -ErrorAction Stop 166 | } 167 | }else{ 168 | Write-Error "The $NetIP is not a network address" -ErrorAction Stop 169 | } 170 | } 171 | 172 | function CheckPortsValidity{ 173 | param( 174 | [Parameter(Mandatory=$true)] 175 | [string]$p 176 | ) 177 | $Ports = @() 178 | #If is a port range 179 | if($p -match "[0-9]+\.\.[0-9]+"){ 180 | [int[]]$Range = $p -split "\.\." 181 | if($Range[0] -ge $Range[1] -or $Range[0] -le 0 -or $Range[1] -le 0 -or $Range[1] -gt 65535){ 182 | Write-Error "Port range is not valid." -ErrorAction Stop 183 | } 184 | $Ports = (Invoke-Expression $p) 185 | } 186 | #If is a set of ports or single port number 187 | elseif($p -match "^(?:[0-9]+,*)+$"){ 188 | $r = Invoke-Expression $p 189 | if($r.GetType().Name -eq "Int32"){ 190 | if([int]$p -ge 0 -and [int]$p -lt 65536){ 191 | $Ports += [int]$p 192 | }else{ 193 | Write-Error "Port number is not valid." -ErrorAction Stop 194 | } 195 | }else{ 196 | ForEach($port in $r){ 197 | if((Invoke-Expression $port) -is [int] -and [int]$port -ge 0 -and [int]$port -lt 65536){ 198 | $Ports += [int]$port 199 | }else{ 200 | Write-Error "Some port number in the set is not valid." -ErrorAction Stop 201 | } 202 | } 203 | } 204 | } 205 | else{ 206 | Write-Error "Is either not a valid port number or set." -ErrorAction Stop 207 | } 208 | return $Ports 209 | } 210 | 211 | function Scan{ 212 | param( 213 | [Parameter(Mandatory=$true)] 214 | [string]$h, 215 | [Parameter(Mandatory=$true)] 216 | [object]$ps, 217 | [Parameter(Mandatory=$true)] 218 | [object]$PortList, 219 | [System.Management.Automation.SwitchParameter]$Open 220 | ) 221 | $res = @() 222 | $i = 1 223 | 224 | ForEach ($p in $ps){ 225 | $port_res = @{} 226 | $port_res["Port"] = $p 227 | 228 | If($PortList.Get_Item($p)){ 229 | $port_res["Service"] = $PortList.Get_Item($p) 230 | }else{ 231 | $port_res["Service"] = "Unkwnown" 232 | } 233 | 234 | 235 | try{ 236 | $socket = New-Object System.Net.Sockets.TcpClient 237 | $connect = $socket.BeginConnect($h,$p, $null, $null) 238 | $wait = $connect.AsyncWaitHandle.WaitOne(100, $false) 239 | 240 | if(-not $wait){ 241 | $port_res["Status"] = "Closed" 242 | }else{ 243 | $port_res["Status"] = "Open" 244 | } 245 | $res += $port_res 246 | }catch{ 247 | $port_res["Status"] = "Closed" 248 | $res += $port_res 249 | } 250 | 251 | #$percentage = ($i / $ps.Length) * 100 252 | #Write-Progress -Id 2 -Activity "Scanning ports..." -Status "Port: $p" -PercentComplete $percentage 253 | $i += 1 254 | } 255 | return $res 256 | } 257 | 258 | function Printer{ 259 | param( 260 | [Parameter(Mandatory=$true)] 261 | [object]$Scan 262 | ) 263 | 264 | ForEach ($target in $Scan){ 265 | Write-Host "Scan results for "$target["Hostname"] 266 | Write-Host "Ping results: "$target["Ping"] 267 | $target["ScanResult"] | ForEach{[PSCustomObject]$_} | Format-Table -AutoSize 268 | } 269 | } 270 | 271 | 272 | 273 | $Hrange = @() 274 | $dPorts = @() 275 | 276 | $PortList = CheckResourceFile 277 | 278 | $t1 = Get-Date 279 | Write-Host "Scan started at: $t1" 280 | Write-Host "----------------------------------------------" 281 | 282 | #If Hosts is an IP address 283 | if ($Hosts -match "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"){ 284 | #If a network address 285 | if ($Hosts -match ".*/[0-9]+$"){ 286 | $Hrange = CalculateNetwork -NetIP $Hosts 287 | #If Hosts is a single IP 288 | }else{ 289 | $Hrange += $Hosts 290 | } 291 | } 292 | #If Hosts is a hostname 293 | else{ 294 | $Hrange += $Hosts 295 | } 296 | #If no hosts to scan 297 | if($Hrange.Length -eq 0){ 298 | Write-Error "No available hosts to scan." -ErrorAction Stop 299 | } 300 | 301 | #Check Port values 302 | $dPorts = CheckPortsValidity -p $Ports 303 | if($dPorts.Length -eq 0){ 304 | Write-Error "No available ports to scan." -ErrorAction Stop 305 | } 306 | 307 | $Result = @() 308 | $i = 1 309 | 310 | #Start Scan 311 | ForEach($target in $Hrange){ 312 | $ObjTarget = @{} 313 | #If DNS resolution 314 | if(-not $n){ 315 | $ObjTarget["Hostname"] = (Resolve-DnsName -Name $target -Type A).IPAddress 316 | }else{ 317 | $ObjTarget["Hostname"] = $target 318 | } 319 | #If Ping option 320 | if(-not $Pn){ 321 | #If host is reachable 322 | if((SendPing -Hostname $target)){ 323 | $ObjTarget["Ping"] = "Reachable" 324 | ##Scan Host 325 | $ObjTarget["ScanResult"] = Scan -h $target -ps $dPorts -PortList $PortList 326 | }else{ 327 | $ObjTarget["Ping"] = "Unreachable" 328 | } 329 | } 330 | #No Ping options 331 | else{ 332 | $ObjTarget["Ping"] = "Not Requested" 333 | ##Scan Host 334 | $ObjTarget["ScanResult"] = Scan -h $target -ps $dPorts -PortList $PortList 335 | } 336 | $percentage = ($i / $Hrange.Length) * 100 337 | Write-Progress -Id 1 -Activity "Scanning Host" -Status "Current host: $target" -PercentComplete $percentage 338 | 339 | $Result += $ObjTarget 340 | $i += 1 341 | } 342 | 343 | Printer -Scan $Result 344 | 345 | Write-Host "----------------------------------------------" 346 | $t2 = Get-Date 347 | $elapsed = ($t2-$t1).totalseconds 348 | Write-Host "Script execution is terminated at: $t2" 349 | Write-Host "Elapsed: " $elapsed 350 | 351 | #PortScanner -Hosts "192.168.1.0/24" -Ports "22,80,443,445" -Pn -n 352 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Powershell-PortScan 2 | Powershell Scripts for Blue Team members. 3 | This script performs TCP port scans, providing the option to specify an entire network. 4 | 5 | ![Examples](./examples.png) 6 | 7 | ## TODO 8 | + Ping Sweep 9 | + Color in output 10 | -------------------------------------------------------------------------------- /examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giuseppe-argento83/Powershell-PortScan/13895810b38d3456ed17d6bde40a553480fa9429/examples.png --------------------------------------------------------------------------------