├── LICENSE ├── README.md └── HostRecon.ps1 /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 dafthack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Invoke-HostRecon 2 | Invoke-HostRecon runs a number of checks on a system to help provide situational awareness to a penetration tester during the reconnaissance phase of an engagement. It gathers information about the local system, users, and domain information. It does not use any 'net', 'ipconfig', 'whoami', 'netstat', or other system commands to help avoid detection. 3 | 4 | For more info check out this blog post: http://www.blackhillsinfosec.com/?p=5824 5 | 6 | HostRecon Demo Video: https://www.youtube.com/watch?v=H4wzhmaBgM0 7 | 8 | ## Situational Awareness 9 | ### Invoke-HostRecon gets the following information from the system without running system tools like 'net', 'ipconfig', etc. 10 | ``` 11 | Current Hostname 12 | IP Information 13 | Current Username 14 | Current Domain Name 15 | All Local Users 16 | Local Admins Group 17 | Netstat Information 18 | DNS Cache Information 19 | Shares 20 | Scheduled Tasks 21 | Web Proxy Information 22 | Process Listing 23 | AntiVirus Information 24 | Firewall Status 25 | Local Admin Password Solution (LAPS) 26 | Domain Password Policy 27 | Domain Admins Group Members 28 | Domain Controllers 29 | Check for Sysinternals Sysmon 30 | Checks for Common Security Products 31 | ``` 32 | ## Common Security Product Detection 33 | Invoke-HostRecon attempts to enumerate common security products on the system including AV, IDS, AppWhitelisting, Behavioral Analysis, etc. 34 | 35 | ## Egress Filter Check 36 | Invoke-HostRecon also includes a functionality for assessing egress filtering from the system. The -Portscan flag can be passed to initiate an outbound portscan against allports.exposed to help determine open ports allowed through an egress firewall. (Credit for the Portscan module goes to Joff Thyer) 37 | 38 | ### Usage Example 39 | This command will run a number of checks on the local system including the retrieval of local system information (netstat, common security products, scheduled tasks, local admins group, LAPS, etc), and domain information (Domain Admins group, DC's, password policy). Additionally, it will perform an outbound portscan on the top 128 ports to allports.exposed to assist in determining any ports that might be allowed outbound for C2 communications. 40 | ``` PowerShell 41 | Invoke-HostRecon -Portscan -TopPorts 128 42 | ``` 43 | -------------------------------------------------------------------------------- /HostRecon.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-HostRecon{ 2 | 3 | <# 4 | 5 | .SYNOPSIS 6 | 7 | This function runs a number of checks on a system to help provide situational awareness to a penetration tester during the reconnaissance phase. It gathers information about the local system, users, and domain information. It does not use any 'net', 'ipconfig', 'whoami', 'netstat', or other system commands to help avoid detection. 8 | 9 | HostRecon Function: Invoke-HostRecon 10 | Author: Beau Bullock (@dafthack) with credit to Joff Thyer (@joff_thyer) for the portscan module. 11 | License: BSD 3-Clause 12 | Required Dependencies: None 13 | Optional Dependencies: None 14 | 15 | .DESCRIPTION 16 | 17 | This function runs a number of checks on a system to help provide situational awareness to a penetration tester during the reconnaissance phase. It gathers information about the local system, users, and domain information. It does not use any 'net', 'ipconfig', 'whoami', 'netstat', or other system commands to help avoid detection. 18 | 19 | .PARAMETER Portscan 20 | 21 | If this flag is added an outbound portscan will be initiated from the target system to allports.exposed. The top 50 ports as specified by the Nmap project will be scanned. This is useful in determining any egress filtering in use. 22 | 23 | .PARAMETER TopPorts 24 | 25 | This flag specifies the number of "top ports" to be scanned outbound from the system. Valid entries are 1-128. Default is 50. 26 | 27 | .Example 28 | 29 | C:\PS> Invoke-HostRecon 30 | 31 | Description 32 | ----------- 33 | This command will run a number of checks on the local system including the retrieval of local system information (netstat, common security products, scheduled tasks, local admins group, LAPS, etc), and domain information (Domain Admins group, DC's, password policy). 34 | 35 | .Example 36 | 37 | C:\PS> Invoke-HostRecon -Portscan -TopPorts 128 38 | 39 | Description 40 | ----------- 41 | This command will run a number of checks on the local system including the retrieval of local system information (netstat, common security products, scheduled tasks, local admins group, LAPS, etc), and domain information (Domain Admins group, DC's, password policy). Additionally, it will perform an outbound portscan on the top 128 ports to allports.exposed to assist in determining any ports that might be allowed outbound for C2 communications. 42 | 43 | #> 44 | 45 | Param( 46 | 47 | [Parameter(Position = 0, Mandatory = $false)] 48 | [switch] 49 | $Portscan, 50 | 51 | [Parameter(Position = 1, Mandatory = $false)] 52 | [string] 53 | $TopPorts = "50", 54 | 55 | [Parameter(Position = 2, Mandatory = $false)] 56 | [switch] 57 | $DisableDomainChecks = $false, 58 | 59 | [ValidateRange(1,65535)][String[]]$Portlist = "" 60 | 61 | ) 62 | 63 | #Hostname 64 | 65 | Write-Output "[*] Hostname" 66 | $Computer = $env:COMPUTERNAME 67 | $Computer 68 | Write-Output "`n" 69 | 70 | #IP Information 71 | 72 | Write-Output "[*] IP Address Info" 73 | $ipinfo = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter 'IPEnabled = True'| Select-Object IPAddress,Description | Format-Table -Wrap | Out-String 74 | $ipinfo 75 | Write-Output "`n" 76 | 77 | #Current user and domain 78 | 79 | Write-Output "[*] Current Domain and Username" 80 | 81 | $currentuser = $env:USERNAME 82 | Write-Output "Domain = $env:USERDOMAIN" 83 | Write-Output "Current User = $env:USERNAME" 84 | Write-Output "`n" 85 | 86 | #All local users 87 | 88 | Write-Output "[*] Local Users of this system" 89 | $locals = Get-WmiObject -Class Win32_UserAccount -Filter "LocalAccount='True'" | Select-Object Name 90 | $locals 91 | Write-Output "`n" 92 | 93 | #Local Admins group 94 | 95 | Write-Output "[*] Local Admins of this system" 96 | $Admins = Get-WmiObject win32_groupuser | Where-Object { $_.GroupComponent -match 'administrators' -and ($_.GroupComponent -match "Domain=`"$env:COMPUTERNAME`"")} | ForEach-Object {[wmi]$_.PartComponent } | Select-Object Caption,SID | format-table -Wrap | Out-String 97 | $Admins 98 | Write-Output "`n" 99 | 100 | #Netstat Information 101 | #Some code here borrowed from: http://techibee.com/powershell/query-list-of-listening-ports-in-windows-using-powershell/2344 102 | Write-Output "[*] Active Network Connections" 103 | $TCPProperties = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties() 104 | $Connections = $TCPProperties.GetActiveTcpConnections() 105 | $objarray = @() 106 | foreach($Connection in $Connections) { 107 | if($Connection.LocalEndPoint.AddressFamily -eq "InterNetwork" ) { $IPType = "IPv4" } else { $IPType = "IPv6" } 108 | $OutputObj = New-Object -TypeName PSobject 109 | $OutputObj | Add-Member -MemberType NoteProperty -Name "LocalAddress" -Value $Connection.LocalEndPoint.Address 110 | $OutputObj | Add-Member -MemberType NoteProperty -Name "LocalPort" -Value $Connection.LocalEndPoint.Port 111 | $OutputObj | Add-Member -MemberType NoteProperty -Name "RemoteAddress" -Value $Connection.RemoteEndPoint.Address 112 | $OutputObj | Add-Member -MemberType NoteProperty -Name "RemotePort" -Value $Connection.RemoteEndPoint.Port 113 | $OutputObj | Add-Member -MemberType NoteProperty -Name "State" -Value $Connection.State 114 | $OutputObj | Add-Member -MemberType NoteProperty -Name "IPV4Or6" -Value $IPType 115 | $objarray += $OutputObj 116 | } 117 | $activeconnections = $objarray | Format-Table -Wrap | Out-String 118 | $activeconnections 119 | 120 | Write-Output "[*] Active TCP Listeners" 121 | $ListenConnections = $TCPProperties.GetActiveTcpListeners() 122 | $objarraylisten = @() 123 | foreach($Connection in $ListenConnections) { 124 | if($Connection.address.AddressFamily -eq "InterNetwork" ) { $IPType = "IPv4" } else { $IPType = "IPv6" } 125 | $OutputObjListen = New-Object -TypeName PSobject 126 | $OutputObjListen | Add-Member -MemberType NoteProperty -Name "LocalAddress" -Value $connection.Address 127 | $OutputObjListen | Add-Member -MemberType NoteProperty -Name "ListeningPort" -Value $Connection.Port 128 | $OutputObjListen | Add-Member -MemberType NoteProperty -Name "IPV4Or6" -Value $IPType 129 | $objarraylisten += $OutputObjListen } 130 | $listeners = $objarraylisten | Format-Table -Wrap | Out-String 131 | $listeners 132 | 133 | Write-Output "`n" 134 | 135 | #DNS Cache Information 136 | 137 | Write-Output "[*] DNS Cache" 138 | 139 | try{ 140 | $dnscache = Get-WmiObject -query "Select * from MSFT_DNSClientCache" -Namespace "root\standardcimv2" -ErrorAction stop | Select-Object Entry,Name,Data | Format-Table -Wrap | Out-String 141 | $dnscache 142 | } 143 | catch 144 | { 145 | Write-Output "There was an error retrieving the DNS cache." 146 | } 147 | Write-Output "`n" 148 | 149 | #Shares 150 | 151 | Write-Output "[*] Share listing" 152 | $shares = @() 153 | $shares = Get-WmiObject -Class Win32_Share | Format-Table -Wrap | Out-String 154 | $shares 155 | Write-Output "`n" 156 | 157 | #Scheduled Tasks 158 | 159 | Write-Output "[*] List of scheduled tasks" 160 | $schedule = new-object -com("Schedule.Service") 161 | $schedule.connect() 162 | $tasks = $schedule.getfolder("\").gettasks(0) | Select-Object Name | Format-Table -Wrap | Out-String 163 | If ($tasks.count -eq 0) 164 | { 165 | Write-Output "[*] Task scheduler appears to be empty" 166 | } 167 | If ($tasks.count -ne 0) 168 | { 169 | $tasks 170 | } 171 | Write-Output "`n" 172 | 173 | #Proxy information 174 | 175 | Write-Output "[*] Proxy Info" 176 | $proxyenabled = (Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings').proxyEnable 177 | $proxyserver = (Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings').proxyServer 178 | 179 | If ($proxyenabled -eq 1) 180 | { 181 | Write-Output "A system proxy appears to be enabled." 182 | Write-Output "System proxy located at: $proxyserver" 183 | } 184 | Elseif($proxyenabled -eq 0) 185 | { 186 | Write-Output "There does not appear to be a system proxy enabled." 187 | } 188 | Write-Output "`n" 189 | 190 | #Getting AntiVirus Information 191 | 192 | 193 | Write-Output "[*] Checking if AV is installed" 194 | 195 | $AV = Get-WmiObject -Namespace "root\SecurityCenter2" -Query "SELECT * FROM AntiVirusProduct" 196 | 197 | If ($AV -ne "") 198 | { 199 | Write-Output "The following AntiVirus product appears to be installed:" $AV.displayName 200 | } 201 | If ($AV -eq "") 202 | { 203 | Write-Output "No AV detected." 204 | } 205 | Write-Output "`n" 206 | 207 | #Getting Local Firewall Status 208 | 209 | Write-Output "[*] Checking local firewall status." 210 | $HKLM = 2147483650 211 | $reg = get-wmiobject -list -namespace root\default -computer $computer | where-object { $_.name -eq "StdRegProv" } 212 | $firewallEnabled = $reg.GetDwordValue($HKLM, "System\ControlSet001\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile","EnableFirewall") 213 | $fwenabled = [bool]($firewallEnabled.uValue) 214 | 215 | If($fwenabled -eq $true) 216 | { 217 | Write-Output "The local firewall appears to be enabled." 218 | } 219 | If($fwenabled -ne $true) 220 | { 221 | Write-Output "The local firewall appears to be disabled." 222 | } 223 | Write-Output "`n" 224 | 225 | #Checking for Local Admin Password Solution (LAPS) 226 | 227 | Write-Output "[*] Checking for Local Admin Password Solution (LAPS)" 228 | try 229 | { 230 | $lapsfile = Get-ChildItem "$env:ProgramFiles\LAPS\CSE\Admpwd.dll" -ErrorAction Stop 231 | if ($lapsfile) 232 | { 233 | Write-Output "The LAPS DLL (Admpwd.dll) was found. Local Admin password randomization may be in use." 234 | } 235 | } 236 | catch 237 | { 238 | Write-Output "The LAPS DLL was not found." 239 | } 240 | Write-Output "`n" 241 | 242 | #Process Information 243 | 244 | Write-Output "[*] Running Processes" 245 | 246 | $processes = Get-Process | Select-Object ProcessName,Id,Description,Path 247 | $processout = $processes | Format-Table -Wrap | Out-String 248 | $processout 249 | Write-Output "`n" 250 | 251 | #Checking for common security products 252 | 253 | Write-Output "[*] Checking for Sysinternals Sysmon" 254 | try 255 | { 256 | $sysmondrv = Get-ChildItem "$env:SystemRoot\sysmondrv.sys" -ErrorAction Stop 257 | if ($sysmondrv) 258 | { 259 | Write-Output "The Sysmon driver $($sysmondrv.VersionInfo.FileVersion) (sysmondrv.sys) was found. System activity may be monitored." 260 | } 261 | } 262 | catch 263 | { 264 | Write-Output "The Sysmon driver was not found." 265 | } 266 | Write-Output "`n" 267 | 268 | Write-Output "[*] Checking for common security product processes" 269 | $processnames = $processes | Select-Object ProcessName 270 | Foreach ($ps in $processnames) 271 | { 272 | #AV 273 | if ($ps.ProcessName -like "*mcshield*") 274 | { 275 | Write-Output ("Possible McAfee AV process " + $ps.ProcessName + " is running.") 276 | } 277 | if (($ps.ProcessName -like "*windefend*") -or ($ps.ProcessName -like "*MSASCui*") -or ($ps.ProcessName -like "*msmpeng*") -or ($ps.ProcessName -like "*msmpsvc*")) 278 | { 279 | Write-Output ("Possible Windows Defender AV process " + $ps.ProcessName + " is running.") 280 | } 281 | if ($ps.ProcessName -like "*WRSA*") 282 | { 283 | Write-Output ("Possible WebRoot AV process " + $ps.ProcessName + " is running.") 284 | } 285 | if ($ps.ProcessName -like "*savservice*") 286 | { 287 | Write-Output ("Possible Sophos AV process " + $ps.ProcessName + " is running.") 288 | } 289 | if (($ps.ProcessName -like "*TMCCSF*") -or ($ps.ProcessName -like "*TmListen*") -or ($ps.ProcessName -like "*NTRtScan*")) 290 | { 291 | Write-Output ("Possible Trend Micro AV process " + $ps.ProcessName + " is running.") 292 | } 293 | if (($ps.ProcessName -like "*symantec antivirus*") -or ($ps.ProcessName -like "*SymCorpUI*") -or ($ps.ProcessName -like "*ccSvcHst*") -or ($ps.ProcessName -like "*SMC*") -or ($ps.ProcessName -like "*Rtvscan*")) 294 | { 295 | Write-Output ("Possible Symantec AV process " + $ps.ProcessName + " is running.") 296 | } 297 | if ($ps.ProcessName -like "*mbae*") 298 | { 299 | Write-Output ("Possible MalwareBytes Anti-Exploit process " + $ps.ProcessName + " is running.") 300 | } 301 | #if ($ps.ProcessName -like "*mbam*") 302 | # { 303 | # Write-Output ("Possible MalwareBytes Anti-Malware process " + $ps.ProcessName + " is running.") 304 | # } 305 | #AppWhitelisting 306 | if ($ps.ProcessName -like "*Parity*") 307 | { 308 | Write-Output ("Possible Bit9 application whitelisting process " + $ps.ProcessName + " is running.") 309 | } 310 | #Behavioral Analysis 311 | if ($ps.ProcessName -like "*cb*") 312 | { 313 | Write-Output ("Possible Carbon Black behavioral analysis process " + $ps.ProcessName + " is running.") 314 | } 315 | if ($ps.ProcessName -like "*bds-vision*") 316 | { 317 | Write-Output ("Possible BDS Vision behavioral analysis process " + $ps.ProcessName + " is running.") 318 | } 319 | if ($ps.ProcessName -like "*Triumfant*") 320 | { 321 | Write-Output ("Possible Triumfant behavioral analysis process " + $ps.ProcessName + " is running.") 322 | } 323 | if ($ps.ProcessName -like "CSFalcon") 324 | { 325 | Write-Output ("Possible CrowdStrike Falcon EDR process " + $ps.ProcessName + " is running.") 326 | } 327 | #Intrusion Detection 328 | if ($ps.ProcessName -like "*ossec*") 329 | { 330 | Write-Output ("Possible OSSEC intrusion detection process " + $ps.ProcessName + " is running.") 331 | } 332 | #Firewall 333 | if ($ps.ProcessName -like "*TmPfw*") 334 | { 335 | Write-Output ("Possible Trend Micro firewall process " + $ps.ProcessName + " is running.") 336 | } 337 | #DLP 338 | if (($ps.ProcessName -like "dgagent") -or ($ps.ProcessName -like "DgService") -or ($ps.ProcessName -like "DgScan")) 339 | { 340 | Write-Output ("Possible Verdasys Digital Guardian DLP process " + $ps.ProcessName + " is running.") 341 | } 342 | if ($ps.ProcessName -like "kvoop") 343 | { 344 | Write-Output ("Possible Unknown DLP process " + $ps.ProcessName + " is running.") 345 | } 346 | } 347 | Write-Output "`n" 348 | 349 | if ($DisableDomainChecks -eq $false) 350 | { 351 | #Domain Password Policy 352 | 353 | $domain = "$env:USERDOMAIN" 354 | Write-Output "[*] Domain Password Policy" 355 | Try 356 | { 357 | $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$domain) 358 | $DomainObject =[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) 359 | $CurrentDomain = [ADSI]"WinNT://$env:USERDOMAIN" 360 | $Name = @{Name="DomainName";Expression={$_.Name}} 361 | $MinPassLen = @{Name="Minimum Password Length";Expression={$_.MinPasswordLength}} 362 | $MinPassAge = @{Name="Minimum Password Age (Days)";Expression={$_.MinPasswordAge.value/86400}} 363 | $MaxPassAge = @{Name="Maximum Password Age (Days)";Expression={$_.MaxPasswordAge.value/86400}} 364 | $PassHistory = @{Name="Enforce Password History (Passwords remembered)";Expression={$_.PasswordHistoryLength}} 365 | $AcctLockoutThreshold = @{Name="Account Lockout Threshold";Expression={$_.MaxBadPasswordsAllowed}} 366 | $AcctLockoutDuration = @{Name="Account Lockout Duration (Minutes)";Expression={if ($_.AutoUnlockInterval.value -eq -1) {'Account is locked out until administrator unlocks it.'} else {$_.AutoUnlockInterval.value/60}}} 367 | $ResetAcctLockoutCounter = @{Name="Observation Window";Expression={$_.LockoutObservationInterval.value/60}} 368 | $CurrentDomain | Select-Object $Name,$MinPassLen,$MinPassAge,$MaxPassAge,$PassHistory,$AcctLockoutThreshold,$AcctLockoutDuration,$ResetAcctLockoutCounter | format-list | Out-String 369 | 370 | } 371 | catch 372 | { 373 | Write-Output "Error connecting to the domain while retrieving password policy." 374 | 375 | } 376 | Write-Output "`n" 377 | 378 | #Domain Controllers 379 | 380 | Write-Output "[*] Domain Controllers" 381 | Try 382 | { 383 | $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$domain) 384 | $DomainObject =[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) 385 | $DCS = $DomainObject.DomainControllers 386 | foreach ($dc in $DCS) 387 | { 388 | $dc.Name 389 | } 390 | 391 | } 392 | catch 393 | { 394 | Write-Output "Error connecting to the domain while retrieving listing of Domain Controllers." 395 | 396 | } 397 | Write-Output "`n" 398 | 399 | #Domain Admins 400 | 401 | Write-Output "[*] Domain Admins" 402 | Try 403 | { 404 | $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$domain) 405 | $DomainObject =[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) 406 | 407 | $DAgroup = ([adsi]"WinNT://$domain/Domain Admins,group") 408 | $Members = @($DAgroup.psbase.invoke("Members")) 409 | [Array]$MemberNames = $Members | ForEach{([ADSI]$_).InvokeGet("Name")} 410 | $MemberNames 411 | } 412 | catch 413 | { 414 | Write-Output "Error connecting to the domain while retrieving Domain Admins group members." 415 | 416 | } 417 | Write-Output "`n" 418 | } 419 | If($Portscan) 420 | { 421 | if ($Portlist -ne "") 422 | { 423 | TCP-PortScan -Portlist $Portlist 424 | } 425 | else 426 | { 427 | TCP-PortScan -TopPorts $TopPorts 428 | } 429 | } 430 | 431 | } 432 | 433 | 434 | function TCP-PortScan { 435 | <# 436 | .SYNOPSIS 437 | 438 | Perform a full TCP connection scan to the destination hostname, or to 'allports.exposed' if that destination is not supplied. 439 | 440 | Author: Joff Thyer, April 2014 441 | 442 | .DESCRIPTION 443 | 444 | TCP-Portscan is designed to perform a full TCP connection scan to the destination 445 | hostname using either a port range of top X number of popular TCP ports. The top 446 | popular port list is derived from NMAP's services using the frequrency measurements 447 | that appear in this file. If the top X number of popular ports is not the desired 448 | behavior, you can specify a minimum and maximum port number within which a range of 449 | ports will be scanned. By default, a random delay between 50 and 200 milliseconds 450 | is added in order to assist in avoiding detection. Also by default, if the hostname 451 | is not specified then 'allports.exposed' will be used as a default. The 'allports.exposed' 452 | site responds to all TCP ports will the text of 'woot woot' if an HTTP request is sent, 453 | but more to the point, all ports are considered open. 454 | 455 | .PARAMETER Hostname 456 | 457 | If provided, the hostname will be looked up and the resulting IP address used 458 | as the IP address to be scanned. If not provided, then the default hostname 459 | of 'allports.exposed' will be used. 460 | 461 | .PARAMETER MinPort 462 | 463 | Specify the minimum port number in a range of ports to be scanned. 464 | 465 | .PARAMETER MaxPort 466 | 467 | Specify the maximum port number in a range of ports to be scanned. 468 | 469 | .PARAMETER TopPorts 470 | 471 | Specify the number of popular ports which you would like to be scanned. Up to 472 | 128 ports may be specified. 473 | 474 | .PARAMETER Timeout 475 | 476 | Specify the TCP connection timeout in the range of 10 - 10000 milliseconds. 477 | 478 | .PARAMETER NoRandomDelay 479 | 480 | Disable the random delay between connection attempts. 481 | 482 | #> 483 | 484 | param( [String]$Hostname = 'allports.exposed', 485 | [ValidateRange(1,65535)][Int]$MinPort = 1, 486 | [ValidateRange(1,65535)][Int]$MaxPort = 1, 487 | [ValidateRange(1,128)][Int]$TopPorts = 50, 488 | [ValidateRange(10,10000)][Int]$Timeout = 400, 489 | [ValidateRange(1,65535)][String[]]$Portlist = "", 490 | [switch]$NoRandomDelay = $false ) 491 | 492 | $resolved = [System.Net.Dns]::GetHostByName($Hostname) 493 | $ip = $resolved.AddressList[0].IPAddressToString 494 | 495 | # TopN port collection derived from NMAP project 496 | $tcp_top128 = 80, 23, 443, 21, 22, 25, 3389, 110, 445, 139, 143, 53, ` 497 | 135, 3306, 8080, 1723, 111, 995, 993, 5900, 1025, 587, 8888, 199, ` 498 | 1720, 465, 548, 113, 81, 6001, 10000, 514, 5060, 179, 1026, 2000, ` 499 | 8443, 8000, 32768, 554, 26, 1433, 49152, 2001, 515, 8008, 49154, 1027, ` 500 | 5666, 646, 5000, 5631, 631, 49153, 8081, 2049, 88, 79, 5800, 106, ` 501 | 2121, 1110, 49155, 6000, 513, 990, 5357, 427, 49156, 543, 544, 5101, ` 502 | 144, 7, 389, 8009, 3128, 444, 9999, 5009, 7070, 5190, 3000, 5432, ` 503 | 3986, 13, 1029, 9, 6646, 49157, 1028, 873, 1755, 2717, 4899, 9100, ` 504 | 119, 37, 1000, 3001, 5001, 82, 10010, 1030, 9090, 2107, 1024, 2103, ` 505 | 6004, 1801, 19, 8031, 1041, 255, 3703, 17, 808, 3689, 1031, 1071, ` 506 | 5901, 9102, 9000, 2105, 636, 1038, 2601, 7000 507 | 508 | $report = @() 509 | if ($MaxPort -gt 1 -and $MinPort -lt $MaxPort) { 510 | $ports = $MinPort..$MaxPort 511 | Write-Host -NoNewline "[*] Scanning $Hostname ($ip), port range $MinPort -> $MaxPort : " 512 | } 513 | elseif ($MaxPort -lt $MinPort) { 514 | Throw "Are you out of your mind? Port range cannot go negative." 515 | } 516 | elseif($Portlist -ne ""){ 517 | $ports = $Portlist 518 | Write-Host -NoNewline "[*] Scanning $Hostname ($ip), using the portlist provided." 519 | } 520 | else { 521 | $PortDiff = $TopPorts - 1 522 | $ports = $tcp_top128[0..$PortDiff] 523 | Write-Host -NoNewline "[*] Scanning $Hostname ($ip), top $TopPorts popular ports : " 524 | } 525 | 526 | $total = 0 527 | $tcp_count = 0 528 | foreach ($port in Get-Random -input $ports -count $ports.Count) { 529 | if (![Math]::Floor($total % ($ports.Count / 10))) { 530 | Write-Host -NoNewline "." 531 | } 532 | $total += 1 533 | $temp = "" | Select Address, Port, Proto, Status, Banner 534 | $temp.Proto = "tcp" 535 | $temp.Port = $port 536 | $temp.Address = $ip 537 | $tcp = new-Object system.Net.Sockets.TcpClient 538 | $connect = $tcp.BeginConnect($ip,$port,$null,$null) 539 | $wait = $connect.AsyncWaitHandle.WaitOne($Timeout,$false) 540 | if (!$wait) { 541 | $error.clear() 542 | $tcp.close() 543 | $temp.Status = "closed" 544 | } 545 | else { 546 | try { 547 | $tcp.EndConnect($connect) 548 | $tcp.Close() 549 | $temp.Status = "open" 550 | $tcp_count += 1 551 | } 552 | catch { 553 | $temp.Status = "reset" 554 | } 555 | } 556 | $report += $temp 557 | 558 | # add random delay if we want it 559 | if (!$NoRandomDelay) { 560 | $sleeptime = Get-Random -Minimum 50 -Maximum 200 561 | Start-Sleep -Milliseconds $sleeptime 562 | } 563 | } 564 | Write-Host 565 | $columns = @{l='IP-Address';e={$_.Address}; w=15; a="left"},@{l='Proto';e={$_.Proto};w=5;a="right"},@{l='Port';e={$_.Port}; w=5; a="right"},@{l='Status';e={$_.Status}; w=4; a="right"} 566 | $report | where {$_.Status -eq "open"} | Sort-Object Port | Format-Table $columns -AutoSize 567 | Write-Output "[*] $tcp_count out of $total scanned ports are open!" 568 | } 569 | --------------------------------------------------------------------------------