SANS Penetration Testing

Pen Test Poster: "White Board" - PowerShell - Built-in Port Scanner!

Board Elements_clean_Built-in Port Scanner!

By Matthew Toussain, Grant Curell



NMAP is an ideal choice for port scanning, but sometimes it may not be a feasible option. Other times a quick check to see if a port is open might be all the detail needed. In these scenarios PowerShell really shines. Let's examine methods to use PowerShell for basic port scanning functionality.



Methods Covered in this Section

PowerShell port scanner:

1..1024 | % {echo ((new-object Net.Sockets.TcpClient).Connect("",$_)) "Port $_ is open!"} 2>$null

Test-Netconnection scan a range of IPs for a single port:

foreach ($ip in 1..20) {Test-NetConnection -Port 80 -InformationLevel "Detailed" 192.168.1.$ip}

PS IP range & port range scanner:

1..20 | % { $a = $_; 1..1024 | % {echo ((new-object Net.Sockets.TcpClient).Connect("10.0.0.$a",$_)) "Port $_ is open!"} 2>$null}

PS test egress filtering:

1..1024 | % {echo ((new-object Net.Sockets.TcpClient).Connect("",$_)) "Port $_ is open!" } 2>$null


To create a PowerShell port scanner in one line we need to combine three distinct components. Creating a range of objects, looping through each object, and outputting information for each to the screen. In the case of PowerShell we can make use of its object oriented nature to facilitate this process.


PowerShell port scanner:
1..1024 | % {echo ((new-object Net.Sockets.TcpClient).Connect("",$_)) "Port $_ is open!"} 2>$null



Command Breakdown

1..1024 | % {echo ((new-object Net.Sockets.TcpClient).Connect("",$_)) "Port $_ is open!"} 2>$null

1. 1..1024 - Creates a range of variables between 1..1024
2. | - The pipe operator passes objects into the loop
3. % - The % operator in PowerShell is an alias for foreach-object, and is used to start a loop. 
The loop executes the content between {} in sequence
4. echo - Print the following output to the screen
5. new-object Net.Sockets.TcpClient - Instantiates an instance of the .Net TcpClient class, allowing us to make socket connections to TCP ports
6. .Connect("",$_)) - Call the Connect function on the TcpClient class with arguments and port $_. $_ is a variable that means current object. 
The current object relates to number (1..1024) that the loop is currently on.
7. "Port $_ is open!") - This prints Port # is open! when the program finds an open port.
8. 2>$null - This tells PowerShell not to display any errors encountered


The range above scans the 1024 low number ports, but it can easily be adjusted ie (22..53), (8000..9000), etc.

Another method available from within PowerShell is the Test-NetConnection command which can dump extended useful information and is very similar:


Test-Netconnection scan a range of IPs for a single port:
foreach ($ip in 1..20) {Test-NetConnection -Port 80 -InformationLevel "Detailed" 192.168.1.$ip}



A major downside to the Test-NetConnection option is that it was not introduced until PowerShell version 4.0.


Command Breakdown

foreach ($ip in 1..20) {Test-NetConnection -Port 80 -InformationLevel "Detailed" 192.168.1.$ip}

1. foreach ($ip in 1..20) {} - Loop through numbers 1 to 20
2. Test-NetConnection - Test-NetConnection is a utility for testing different types of network connectivity.
3. -Port 80 - Check the availability of port 80
4. -InformationLevel "Detailed" - Provide detailed output information
5. 192.168.1.$ip - Attempt to connect to port 80 against the listed IP address. 
The $ip variable loops from 1-20 in this example.


Building a scanner that iterates through systems and ports is possible as well:


PS IP range & port range scanner:
1..20 | % { $a = $_; 1..1024 | % {echo ((new-object Net.Sockets.TcpClient).Connect("10.0.0.$a",$_)) "Port $_ is open!"} 2>$null}



This version of the command will scan IP addresses and ports 1-1024. Be advised, it may take a while to complete. A more efficient alternative might be to specify the ports to look for manually. Like this:


PS IP range & port range scanner v2:
1..20 | % { $a = $_; write-host "------"; write-host "10.0.0.$a"; 22,53,80,445 | % {echo ((new-object Net.Sockets.TcpClient).Connect("10.0.0.$a",$_)) "Port $_ is open!"} 2>$null}



Bonus Command - Testing Egress Filtering

Many secure environments enable egress filtering controls to limit outbound protocol access to necessary services. This is one of the reasons it is advantageous to leverage HTTP/HTTPS/DNS channels where possible however, when in need of identifying alternative outbound access we can use PowerShell internally to evaluate egress filters on the network firewall.


PS test egress filtering:
1..1024 | % {echo ((new-object Net.Sockets.TcpClient).Connect("",$_)) "Port $_ is open" } 2>$null



For more information on PowerShell egress testing Beau Bullock with Black Hills Information Security has a detailed write-up here:



PowerShell is a robust tool that can accomplish nearly anything when unleash on a Windows environment. Tinker with new and unique combinations of the commands discussed here and feel free to include your improvements in the comments below.

Matthew Toussain


Upcoming SANS Special Event - 2018 Holiday Hack Challenge


SANS Holiday Hack Challenge - KringleCon 2018

  • Free SANS Online Capture-the-Flag Challenge
  • Our annual gift to the entire Information Security Industry
  • Designed for novice to advanced InfoSec professionals
  • Fun for the whole family!!
  • Build and hone your skills in a fun and festive roleplaying like video game, by the makers of SANS NetWars
  • Learn more:
  • Play previous versions from free 24/7/365:

Player Feedback!

  • "On to level 4 of the #holidayhackchallenge. Thanks again @edskoudis / @SANSPenTest team." - @mikehodges
  • "#SANSHolidayHack Confession — I have never used python or scapy before. I got started with both today because of this game! Yay!" - @tww2b
  • "Happiness is watching my 12 yo meet @edskoudis at the end of #SANSHolidayHack quest. Now the gnomes #ProudHackerPapa" - @dnlongen


Posted March 14, 2017 at 5:08 AM | Permalink | Reply


Nevermind, I read the reference article and found, "AllPorts.Exposed is an Internet-resident system with (as the name suggests) all 65535 TCP ports open on it. If you were to portscan it from a system/network without firewall protection you should see that all ports are open. Now, if you were to portscan this system from within your network protected by a firewall, and you see open ports, these ports can be assumed as being allowed outbound through the firewall."
ok, that explains it.

Posted December 7, 2018 at 6:00 PM | Permalink | Reply


many thanks for useful oneliners. Just to note, it takes ages to wait until the connect times out. Maybe you could show how to set the timeout property for the tcpConnect object within oneliner. Thanks!

Posted November 4, 2019 at 9:13 PM | Permalink | Reply


In the script in this section:
PS IP range

Post a Comment


* Indicates a required field.