NMAP without NMAP - Port Testing and Scanning with PowerShell
Ever needed to do a portscan and didn't have nmap installed? I've had this more than once on an internal pentest or more often just on run-rate "is that port open? / is there a host firewall in the way?" testing.
Often we see folks doing something cludgy with telnet or ftp, but Powershell Test-NetConnection (tnc for short) does a fine job of spot testing for an open port or to see if an IP is in use.
For a quick ping test, run tnc with just the target host as an argument:
PS L:\> tnc 8.8.8.8 ComputerName : 8.8.8.8 RemoteAddress : 8.8.8.8 InterfaceAlias : Ethernet 2 SourceAddress : 192.168.122.201 PingSucceeded : True PingReplyDetails (RTT) : 15 ms |
For a quick traceroute:
PS L:\> tnc 8.8.8.8 -traceroute ComputerName : 8.8.8.8 RemoteAddress : 8.8.8.8 InterfaceAlias : Ethernet 2 SourceAddress : 192.168.122.201 PingSucceeded : True PingReplyDetails (RTT) : 13 ms TraceRoute : 192.168.122.1 99.254.226.1 66.185.90.177 24.156.147.129 209.148.235.222 72.14.216.54 108.170.228.0 172.253.69.113 8.8.8.8 |
Limiting the hopcount of traceroute:
PS L:\> tnc 8.8.8.8 -traceroute -hops 3 WARNING: Trace route to destination 8.8.8.8 did not complete. Trace terminated :: 66.185.90.177 ComputerName : 8.8.8.8 RemoteAddress : 8.8.8.8 InterfaceAlias : Ethernet 2 SourceAddress : 192.168.122.201 PingSucceeded : True PingReplyDetails (RTT) : 16 ms TraceRoute : 192.168.122.1 99.254.226.1 66.185.90.177 |
Testing an open port:
PS L:\> tnc 8.8.8.8 -port 443 ComputerName : 8.8.8.8 RemoteAddress : 8.8.8.8 RemotePort : 443 InterfaceAlias : Ethernet 2 SourceAddress : 192.168.122.201 TcpTestSucceeded : True |
Or, for a (not so) quick port scan:
$ip = "192.168.122.241" $result = @() for ($port = 9099; $port -le 9101 ; $port ++) { $result += (tnc $ip -port $port) | select remoteport, tcptestsucceeded } PS L:\> $result RemotePort TcpTestSucceeded ---------- ---------------- 9099 False 9100 True 9101 False |
Or if you just want the open ports:
$ip = "192.168.122.241" $result = @() for ($port = 9099; $port -le 9101 ; $port ++) { $a = (tnc $ip -port $port) | select remoteport, tcptestsucceeded if ($a.tcptestsucceeded ) { $result += $a } } |
As you may have noticed, tnc is a decent tool for testing a single port, but for a portscan it makes for the slowest tool ever. It is however a a great tool for troubleshooting an individual service because the syntax is so easy to remember in a pinch. Using Net.Sockets directly makes for a much faster scan, with slightly more complicated syntax:
new-object system.net.sockets.tcpclient -argumentlist "192.168.122.241","9100"
(yes, system.net.sockets.udpclient is also a thing, everything below works for udp too)
So our port scanner morphs to:
$targetservers = "192.168.122.241", "192.168.122.1" $ports = "22","23","80","443","9100" $result = @() foreach ($target in $targetservers) { foreach ($port in $ports) { $a = new-object system.net.sockets.tcpclient -argumentlist $target,$port if ($a.connected) { $r = new-object -type psobject $r | add-member -membertype noteproperty -name host -value $target $r | add-member -membertype noteproperty -name port -value $port $r | add-member -membertype noteproperty -name state -value "Open" $result += $r } } } |
Hmm, this still takes forever to come back from closed ports. How about this adding in a 100ms timeout on each connection - you can play with that number as needed:
$targetservers = "192.168.122.241", "192.168.122.1" $ports = "22","23","80","443","9100" $result = @() foreach ($target in $targetservers) { foreach ($port in $ports) { $obj = new-Object system.Net.Sockets.TcpClient $connect = $obj.BeginConnect($target,$port,$null,$null) $Wait = $connect.AsyncWaitHandle.WaitOne(100,$false) If (-Not $Wait) { write-host $target 'port' $port 'Closed - Timeout' } else { $value = "Open" write-host $target 'port' $port $value $r = new-object -type psobject $r | add-member -membertype noteproperty -name host -value $target $r | add-member -membertype noteproperty -name port -value $port $r | add-member -membertype noteproperty -name state -value $value $result += $r } } } 192.168.122.241 port 22 Closed - Timeout 192.168.122.241 port 23 Closed - Timeout 192.168.122.241 port 80 Open 192.168.122.241 port 443 Open 192.168.122.241 port 9100 Open 192.168.122.1 port 22 Open 192.168.122.1 port 23 Closed - Timeout 192.168.122.1 port 80 Open 192.168.122.1 port 443 Open 192.168.122.1 port 9100 Closed - Timeout
PS L:\> $result host port state ---- ---- ----- 192.168.122.241 80 Open 192.168.122.241 443 Open 192.168.122.241 9100 Open 192.168.122.1 22 Open 192.168.122.1 80 Open 192.168.122.1 443 Open |
You can of course play with this final script as needed - For instance if you wanted to do a whole range of ports you might change the"foreach ($port in $ports)" loop back to a for loop:
$lport = 0
$hport = 65535
for ($port = $lport; $port -le $hport ; $port ++)
Or if you wanted to scan a /24 subnet, you might change the "foreach ($target in $targetservers) " loop to:
$net = "192.168.122."
for ($h = 1; $h -le 254 ; $h++)
$target = $net+$h
This set of approaches is NOT meant to replace NMAP - for instance I can't tell you for instance how often I use NMAP scripts in a week! However, if you are testing a site-to-site VPN, testing a router or firewall ACL, or checking a host firewall, almost always the host you are testing from is a customer's server, and you won't have NMAP available. Considering that for so many people, the go-to test is to install a telnet (bad idea), then test for an open port using "telnet <target> <port>", with success being a blank screen, these approaches give you a LOT quicker and a LOT more reliably.
If you've got a any improvements to these scripts. in particular maybe a better way to indicate why a port might be not open (for instance - did it time out, send an ICMP port unreachable ro send a RST?) - by all means post to our comment section. The scripts and snips I posted are only as good as they needed to be the last time I needed them, by all means lets make these better!
References:
Test-Netconnection:
https://learn.microsoft.com/en-us/previous-versions/windows/powershell-scripting/dn372891(v=wps.630)
system.Net.Sockets.TcpClient
https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient?view=net-6.0
===============
Rob VandenBrink
rob@coherentsecurity.com
Comments
www
Nov 17th 2022
6 months ago
EEW
Nov 17th 2022
6 months ago
qwq
Nov 17th 2022
6 months ago
mashood
Nov 17th 2022
6 months ago
isc.sans.edu
Nov 23rd 2022
6 months ago
isc.sans.edu
Nov 23rd 2022
6 months ago
isc.sans.edu
Dec 3rd 2022
5 months ago
isc.sans.edu
Dec 3rd 2022
5 months ago
<a hreaf="https://technolytical.com/">the social network</a> is described as follows because they respect your privacy and keep your data secure. The social networks are not interested in collecting data about you. They don't care about what you're doing, or what you like. They don't want to know who you talk to, or where you go.
<a hreaf="https://technolytical.com/">the social network</a> is not interested in collecting data about you. They don't care about what you're doing, or what you like. They don't want to know who you talk to, or where you go. The social networks only collect the minimum amount of information required for the service that they provide. Your personal information is kept private, and is never shared with other companies without your permission
isc.sans.edu
Dec 26th 2022
5 months ago
isc.sans.edu
Dec 26th 2022
5 months ago