Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell TCP port scanner

Tags:

powershell

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.


2 Answers

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 
    }
}
like image 141
postanote Avatar answered Aug 01 '26 16:08

postanote


. Hello, Team!

I have pretty nice solution.

Advances:

  • Parallel scan multiple ports
  • Support TCP, UDP protocols
  • Show banner from remote
  • Configured parameters

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
    }

}
like image 26
Alexey I. Kuzhel Avatar answered Aug 01 '26 17:08

Alexey I. Kuzhel