Exploring the Powershell Alternative to netstat

This post is going to be a very quick rundown of Get-NetTCPConnection, the Powershell cmdlet that serves as a powerful alternative to netstat.

Note: In any comparisons I make between netstat and Get-NetTCPConnection, I am referring to the Windows implementation of netstat.

Why you might want to use Get-NetTCPConnection

  • Easier to get targetted information by filtering on any properties
  • You never have to google how to use it (just use Get-Help and Get-Member)
  • Tab completion
  • Easier to get present specific data in a spcific format (select, sort, etc)
  • Easier to generate things like reports (use pipe and select to output specifics to html or csv
  • Everything is actionable (pipe your results another cmdlet, example down below)

Why you might want to use netstat

  • It’s cross-platform (Get-NetTCPConnection does not work yet on Powershell for Linux as it’s part of .Net Core)
  • You are looking for UDP traffic (you have to use an entirely separate cmdlet for UDP)

Using Get-NetTCPConnection

The first thing I do when discovering a cmdlet is look at the methods and properties available. Do this by running

Get-NetTCPConnection | gm

gm.png

As with most cmdlets, the properties make it pretty clear how to access the information you want. To get anything that’s listening you can run

Get-NetTCPConnection | ? {$_.State -eq "Listen"}

Let’s make it more specific and check for anything that’s listening from any remote address

Get-NetTCPConnection | ? {($_.State -eq "Listen") -and ($_.RemoteAddress -eq "0.0.0.0")}

Now let’s look at what’s listening on port 443, and just display the process responsible, the local port, the state, and the remote address

443

Just like most other get cmdlets, this information can easily be output to a file in a nice format. In this case I’m going to get TCP connections which are listening for connections from any remote address and export all properties of those connections to a CSV

Get-NetTCPConnection | ? {($_.State -eq "Listen") -and ($_.RemoteAddress -eq "0.0.0.0")} | select * | Export-Csv net-connect.csv -NoTypeInformation

And because of Powershell’s object-oriented nature, it’s very easy to relate and take action on the queries you make. For example, let’s say I want to take this same query, everything listening to requests from any IP, and correlate that information to the appropriate process name

$processes = (Get-NetTCPConnection | ? {($_.State -eq "Listen") -and ($_.RemoteAddress -eq "0.0.0.0")}).OwningProcess

foreach ($process in $processes) {Get-Process -PID $process | select ID,ProcessName}

linked-cropped1

Or as a last example, maybe I want to take it a step further and and kill all of those processes responsible (don’t do this).

foreach ($process in $processes) {Get-Process -PID $process | Stop-Process -Force}

One thought on “Exploring the Powershell Alternative to netstat

  1. Hi Matthickok,

    There is another way to get all the netstat data through PowerShell using C#.
    Just take a look at my little script 😉

    [string]$source = @”
    using System;
    using System.Net;
    using System.Runtime.InteropServices;

    public class NetworkUtil
    {
    [DllImport(“iphlpapi.dll”, SetLastError = true)]
    static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwOutBufLen, bool sort, int ipVersion, TCP_TABLE_CLASS tblClass, int reserved);
    [DllImport(“iphlpapi.dll”, SetLastError = true)]
    static extern uint GetExtendedUdpTable(IntPtr pUdpTable, ref int dwOutBufLen, bool sort, int ipVersion, UDP_TABLE_CLASS tblClass, int reserved);

    [StructLayout(LayoutKind.Sequential)]
    public struct MIB_TCPROW_OWNER_PID
    {
    public uint dwState;
    public uint dwLocalAddr;
    public uint dwLocalPort;
    public uint dwRemoteAddr;
    public uint dwRemotePort;
    public uint dwOwningPid;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MIB_UDPROW_OWNER_PID
    {
    public uint dwLocalAddr;
    public uint dwLocalPort;
    public uint dwOwningPid;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MIB_TCPTABLE_OWNER_PID
    {
    public uint dwNumEntries;
    MIB_TCPROW_OWNER_PID table;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MIB_UDPTABLE_OWNER_PID
    {
    public uint dwNumEntries;
    MIB_UDPROW_OWNER_PID table;
    }

    enum TCP_TABLE_CLASS
    {
    TCP_TABLE_BASIC_LISTENER,
    TCP_TABLE_BASIC_CONNECTIONS,
    TCP_TABLE_BASIC_ALL,
    TCP_TABLE_OWNER_PID_LISTENER,
    TCP_TABLE_OWNER_PID_CONNECTIONS,
    TCP_TABLE_OWNER_PID_ALL,
    TCP_TABLE_OWNER_MODULE_LISTENER,
    TCP_TABLE_OWNER_MODULE_CONNECTIONS,
    TCP_TABLE_OWNER_MODULE_ALL
    }

    enum UDP_TABLE_CLASS
    {
    UDP_TABLE_BASIC,
    UDP_TABLE_OWNER_PID,
    UDP_OWNER_MODULE
    }

    public static Connection[] GetTCP()
    {
    MIB_TCPROW_OWNER_PID[] tTable;
    int AF_INET = 2;
    int buffSize = 0;

    uint ret = GetExtendedTcpTable(IntPtr.Zero, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL, 0);
    IntPtr buffTable = Marshal.AllocHGlobal(buffSize);

    try
    {
    ret = GetExtendedTcpTable(buffTable, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL, 0);
    if (ret != 0)
    {
    Connection[] con = new Connection[0];
    return con;
    }

    MIB_TCPTABLE_OWNER_PID tab = (MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(buffTable, typeof(MIB_TCPTABLE_OWNER_PID));
    IntPtr rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(tab.dwNumEntries));
    tTable = new MIB_TCPROW_OWNER_PID[tab.dwNumEntries];

    for (int i = 0; i < tab.dwNumEntries; i++)
    {
    MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal.PtrToStructure(rowPtr, typeof(MIB_TCPROW_OWNER_PID));
    tTable[i] = tcpRow;
    rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow)); // next entry
    }
    }
    finally
    { Marshal.FreeHGlobal(buffTable);}
    Connection[] cons = new Connection[tTable.Length];

    for(int i=0; i < tTable.Length; i++)
    {
    IPAddress localip = new IPAddress(BitConverter.GetBytes(tTable[i].dwLocalAddr));
    IPAddress remoteip = new IPAddress(BitConverter.GetBytes(tTable[i].dwRemoteAddr));
    byte[] barray = BitConverter.GetBytes(tTable[i].dwLocalPort);
    int localport = (barray[0] * 256) + barray[1];
    barray = BitConverter.GetBytes(tTable[i].dwRemotePort);
    int remoteport = (barray[0] * 256) + barray[1];
    string state;
    switch (tTable[i].dwState)
    {
    case 1:
    state = "Closed";
    break;
    case 2:
    state = "LISTENING";
    break;
    case 3:
    state = "SYN SENT";
    break;
    case 4:
    state = "SYN RECEIVED";
    break;
    case 5:
    state = "ESTABLISHED";
    break;
    case 6:
    state = "FINSIHED 1";
    break;
    case 7:
    state = "FINISHED 2";
    break;
    case 8:
    state = "CLOSE WAIT";
    break;
    case 9:
    state = "CLOSING";
    break;
    case 10:
    state = "LAST ACKNOWLEDGE";
    break;
    case 11:
    state = "TIME WAIT";
    break;
    case 12:
    state = "DELETE TCB";
    break;
    default:
    state = "UNKNOWN";
    break;
    }
    Connection tmp = new Connection(localip, localport, remoteip, remoteport, (int)tTable[i].dwOwningPid, state);
    cons[i] = (tmp);
    }
    return cons;
    }

    public static Connection[] GetUDP()
    {
    MIB_UDPROW_OWNER_PID[] tTable;
    int AF_INET = 2; // IP_v4
    int buffSize = 0;

    uint ret = GetExtendedUdpTable(IntPtr.Zero, ref buffSize, true, AF_INET, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID, 0);
    IntPtr buffTable = Marshal.AllocHGlobal(buffSize);

    try
    {
    ret = GetExtendedUdpTable(buffTable, ref buffSize, true, AF_INET, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID, 0);
    if (ret != 0)
    {//none found
    Connection[] con = new Connection[0];
    return con;
    }
    MIB_UDPTABLE_OWNER_PID tab = (MIB_UDPTABLE_OWNER_PID)Marshal.PtrToStructure(buffTable, typeof(MIB_UDPTABLE_OWNER_PID));
    IntPtr rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(tab.dwNumEntries));
    tTable = new MIB_UDPROW_OWNER_PID[tab.dwNumEntries];

    for (int i = 0; i < tab.dwNumEntries; i++)
    {
    MIB_UDPROW_OWNER_PID udprow = (MIB_UDPROW_OWNER_PID)Marshal.PtrToStructure(rowPtr, typeof(MIB_UDPROW_OWNER_PID));
    tTable[i] = udprow;
    rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(udprow));
    }
    }
    finally
    { Marshal.FreeHGlobal(buffTable);}
    Connection[] cons = new Connection[tTable.Length];

    for (int i = 0; i < tTable.Length; i++)
    {
    IPAddress localip = new IPAddress(BitConverter.GetBytes(tTable[i].dwLocalAddr));
    byte[] barray = BitConverter.GetBytes(tTable[i].dwLocalPort);
    int localport = (barray[0] * 256) + barray[1];
    Connection tmp = new Connection(localip, localport, (int)tTable[i].dwOwningPid);
    cons[i] = tmp;
    }
    return cons;
    }
    }

    public class Connection
    {
    private IPAddress _localip, _remoteip;
    private int _localport, _remoteport, _pid;
    private string _state, _proto;
    public Connection(IPAddress Local, int LocalPort, IPAddress Remote, int RemotePort, int PID, string State)
    {
    _proto = "TCP";
    _localip = Local;
    _remoteip = Remote;
    _localport = LocalPort;
    _remoteport = RemotePort;
    _pid = PID;
    _state = State;
    }
    public Connection(IPAddress Local, int LocalPort, int PID)
    {
    _proto = "UDP";
    _localip = Local;
    _localport = LocalPort;
    _pid = PID;
    }
    public IPAddress LocalIP { get{ return _localip;}}
    public IPAddress RemoteIP{ get{return _remoteip;}}
    public int LocalPort{ get{return _localport;}}
    public int RemotePort{ get { return _remoteport; }}
    public int PID{ get { return _pid; }}
    public string State{ get { return _state; }}
    public string Protocol{get { return _proto; }}
    public string PIDName{ get { return (System.Diagnostics.Process.GetProcessById(_pid)).ProcessName; } }
    }
    "@

    Add-Type -TypeDefinition $source -Language CSharp

    [NetworkUtil]::GetUDP() + [NetworkUtil]::GetTCP() | Format-Table

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s