Netstat Local and Remote -new and improved, now with more PowerShell!
Hi again, time for more Powershell!
This all started with me troubleshooting on a customer's server, and cursing Microsoft's decision to spread the output of "netstat -naob" across two lines. Likely they made that decision out of spite - you know, just so I can't grep the information that I actually need out of it.
Which got me to thinking about doing this in Powershell. It'll be easy I thought, just slam together the output of:
Get-Process
Get-NetTCPConnection
Get-NetUDPEndpoint
Join them up into one list, and dump the output right?
Hmm... except that to do a Get-Process with the associated account info (the -IncludeUserName option), you need elevated rights. So that means I need a check for that. And wait, the fields don't *exactly* match up, and the Get-NetUDPEndpoint doesn't actually spell out what's listening, we need to stuff that into the field ... OK, it did get a bit complicated once I got into it. The final script for both TCP and UDP is below. Note that you'll only get the account info if you run it with admin rights:
$Processes = @{} # first check if we're running elevated or not, so we don't error out on the Get-Process command if ((New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) # Query Listening UDP Ports (No Connections in UDP) $Ports += $UDPPorts $Ports | ft PS C:\> $Ports | ft LocalAddress RemoteAddress Proto LocalPort RemotePort State PID UserName ProcessName Path
|
So now, if you want just the listening ports, you can get that with a simple grep:
PS C:\> $ports | ? State -eq 'Listen' | ft LocalAddress RemoteAddress Proto LocalPort RemotePort State PID UserName ProcessName Path
|
With that done, I got to thinking - what about running this across an entire domain, and then look for "outliers" - listening ports that only 1 or 2 hosts have open?? What would that look like?
GetProcess has a -ComputerName option, so we're good there.
Get-NetTCPConnection doesn't have a -ComputerName option, but it does have a -RemoteAddress option
However .. Get-NetUDPEndpoint has neither - local execution only (insert sad panda face here)
I guess we'll need to do this all remotely then - we'll make the whole script so far into a function, then call it using invoke-command for all stations in a domain - like this:
function PSNetstat { if ((New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) # Query Listening UDP Ports (No Connections in UDP) $Ports += $UDPPorts
foreach ($targethost in $targets) { |
Now you have all TCP and UDP ports, in all states in one giant CSV. If you want, you can pull out the just listening ports using the "grep" method we used earlier, and you can mix-and-match it any way you please in either PowerShell or in Excel (we dumped it all into a CSV at the end).
Use our comment form if you run this and find anything odd in your network, we're always interested in "odd"
===============
Rob VandenBrink
www.coherentsecurity.com
Comments