I would like to create a powershell script to perform a TCP port scanner that can list the open TCP ports for a given IP address. here is what I did so far, this is not perfect and I would love some feedback and corrections
port = (80)
network = (192.168.0)
ErrorActionPreference= ‘silentlycontinue’
{ $ip = “{0}.{1}” –F $network,$add
If(Test-Connection –BufferSize 32 –Count 1 –quiet –ComputerName $ip)
{ $socket = new-object System.Net.Sockets.TcpClient($ip, $port)
the problem with this is doesn't scan all the TCP port, and I am not sure how to make it do that.
There are modules you can leverage for this use case.
Find-Module -Name '*nmap*' |
Format-Table -AutoSize
<#
Version Name Repository Description
------- ---- ---------- -----------
1.0.7 xNmap PSGallery Powershell DSC Configuration Script for installing Nmap versions 6.49 (Beta 4), 6.47, 6.46, 6.45, 6.40, and 6.25...
0.6.0 PoshNmap PSGallery A wrapper for NMAP Network Discovery
1.3.1 PSnmap PSGallery Svendsen Tech's PSnmap is an asynchronous Linux nmap look-alike for PowerShell. Ping sweeps and scans a network (accepts CIDR notation) for s...
...
#>
Why not use the purpose-built cmdlet for this use case?
# get function / cmdlet details
Get-Command -Name Test-NetConnection -Syntax
(Get-Command -Name Test-NetConnection).Parameters.Keys
Get-help -Name Test-NetConnection -Full
Get-help -Name Test-NetConnection -Online
Get-help -Name Test-NetConnection -Examples
Point of note:
Earlier Windows PowerShell versions do not have Test-NetConnection if that is your use case, but even then, why do this from scratch, vs leveraging existing samples and tweaking as needed?
Well, unless this is just a learning exercise. Even then that does not mean you'd not look to other examples first.
'powershell tcp port scanner'
Samples provided by the search string.
# Example 01
<#
Creating a Port Scanner with Windows PowerShell
https://devblogs.microsoft.com/scripting/creating-a-port-scanner-with-windows-powershell
#>
# Creating a Port Scanner with Windows PowerShell
$port = 80
$net = “192.168.0”
$range = 1..254
foreach ($r in $range)
{
$ip = “{0}.{1}” -F $net,$r
if(Test-Connection -BufferSize 32 -Count 1 -Quiet -ComputerName $ip)
{
$socket = new-object System.Net.Sockets.TcpClient($ip, $port)
If($socket.Connected)
{
"$ip listening to port $port"
$socket.Close() }
}
}
# Example 02
<#
Port scan subnets with PSnmap for PowerShell
https://www.powershelladmin.com/wiki/Port_scan_subnets_with_PSnmap_for_PowerShell
#>
# Port scan subnets with PSnmap for PowerShell
#$computer, $port = $args[0,1] # assign values to these
$mysock = new-object net.sockets.tcpclient
$IAsyncResult = [IAsyncResult] $mysock.BeginConnect($computer, $port, $null, $null)
measure-command { $succ = $iasyncresult.AsyncWaitHandle.WaitOne(3000, $true) } | % totalseconds
$succ
$mysock.Connected
$mysock.Dispose()
# Example 03:
<#
A Simple Network Port Scanner in PowerShell
https://www.nextofwindows.com/a-simple-network-port-scanner-in-powershell
#>
# #requires -Version 1
function Test-Port
{
Param([string]$ComputerName,$port = 5985,$timeout = 1000)
try
{
$tcpclient = New-Object -TypeName system.Net.Sockets.TcpClient
$iar = $tcpclient.BeginConnect($ComputerName,$port,$null,$null)
$wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
if(!$wait)
{
$tcpclient.Close()
return $false
}
else
{
# Close the connection and report the error if there is one
$null = $tcpclient.EndConnect($iar)
$tcpclient.Close()
return $true
}
}
catch
{
$false
}
}
. Hello, Team!
I have pretty nice solution.
Advances:
EXAMPLE:
Test-Port -ComputerName $ComputerName -Port $Port [-Protocol $Protocol="TCP"] [-Timeout $Timeout=1000] [-ThrottleLimit $ThrottleLimit=1024] [-ReceiveBufferSize $ReceiveBufferSize=2048] [-PortHelper $PortHelper] [-Banner $Banner]
PS. Tested on powershell 7
function Test-Port {
<#
.SYNOPSIS
Test port
.EXAMPLE
Test-Port -ComputerName $ComputerName -Port $Port [-Protocol $Protocol="TCP"] [-Timeout $Timeout=1000] [-ThrottleLimit $ThrottleLimit=1024] [-ReceiveBufferSize $ReceiveBufferSize=2048] [-PortHelper $PortHelper] [-Banner $Banner]
.NOTES
AUTHOR Alexk
CREATED 07.04.21
VER 1
#>
[CmdletBinding()]
param (
[Parameter( Mandatory = $true, Position = 0, HelpMessage = "Computer name." )]
[string] $ComputerName,
[Parameter( Mandatory = $true, Position = 1, HelpMessage = "Port number." )]
[int[]] $Port,
[Parameter( Mandatory = $false, Position = 2, HelpMessage = "Protocol name." )]
[ValidateSet("TCP","UDP")]
[string] $Protocol = "TCP",
[Parameter( Mandatory = $false, Position = 3, HelpMessage = "Connection timeout in milliseconds." )]
[int] $Timeout = 1000,
[Parameter( Mandatory = $false, Position = 4, HelpMessage = "Simultanius thread number." )]
[int] $ThrottleLimit = 1024,
[Parameter( Mandatory = $false, Position = 5, HelpMessage = "Receive buffer size in bytes." )]
[int] $ReceiveBufferSize = 2048,
[Parameter( Mandatory = $false, Position = 6, HelpMessage = "Port helper. Help object with details oboit ports." )]
[PSobject[]] $PortHelper,
[Parameter( Mandatory = $false, Position = 7, HelpMessage = "Get remote banner." )]
[switch] $Banner
)
begin {
$result = @()
}
process {
$result += $Port | ForEach-Object -Parallel {
try {
$ComputerName = $Using:ComputerName
$Protocol = $Using:protocol
$Timeout = $Using:Timeout
$Banner = $Using:Banner
$ReceiveBufferSize = $Using:ReceiveBufferSize
$Port = $_
$Result = $Null
if ( $protocol -eq "TCP" ){
$Client = [System.Net.Sockets.TcpClient]::new()
[void] $Client.ConnectAsync( $ComputerName, $Port ).Wait( $Timeout )
$Connected = $Client.Connected
}
Else {
$Client = [System.Net.Sockets.UdpClient]::new()
[void] $Client.Connect( $ComputerName, $Port )
$Connected = $True
}
$PSO = [PSCustomObject]@{
RemoteHostname = $ComputerName
Protocol = $protocol
RemotePort = $Port
Opened = $Connected
TimeoutInMillisecond = $Timeout
SourceHostname = $env:COMPUTERNAME
}
if ( $Banner -and $Connected -and ( $Protocol -eq "TCP" ) ){
$Stream = $Client.GetStream()
$Stream.ReadTimeOut = $Timeout
if ( $Stream.CanRead ){
$Data = [System.Byte[]]::new( $ReceiveBufferSize )
[void] $Stream.Read( $Data, 0, $Data.Length ) #| Out-Null
$BannerText = ( [System.Text.Encoding]::ASCII.GetString( $Data ) ).Trim( [char]$null )
}
$Stream.Dispose()
$PSO | Add-Member -NotePropertyName "Banner" -NotePropertyValue $BannerText
}
$Client.Dispose()
$result = $PSO
}
Catch {
switch ( $_.Exception.HResult ) {
-2146233087 {
#timeout
if ( $Stream ){
$Stream.Dispose()
}
$Client.Dispose()
$PSO | Add-Member -NotePropertyName "Banner" -NotePropertyValue ""
$result = $PSO
}
Default {
Add-ToLog -Message "Error while connecting [$ComputerName] on [$( $protocol ):$( $Port )].`n$_" -logFilePath $Global:gsScriptLogFilePath -Display -category "test-port" -Status "error"
$result = @()
}
}
}
return $result
} -ThrottleLimit $ThrottleLimit
}
end {
if ( $PortHelper ){
foreach ( $item in $result ){
$Selected = $PortHelper | Where-Object { ( $_.Port -eq $item.RemotePort ) -and ( $item.Protocol -in ($_.Protocol.split(',')) )}
if ( $Selected ){
$item | Add-Member -NotePropertyName 'Description' -NotePropertyValue "$($Selected.Description) ($($Selected.Status))"
}
}
}
return $result
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With