# encoding: ascii
# api: powershell
# title: Get-Netstat
# description: This will perform a basic netstat.exe command and “objectize” its output.  
# version: 1.2
# type: function
# author: glnsize
# license: CC0
# function: Get-Netstat
# x-poshcode-id: 3139
# x-archived: 2016-06-10T16:03:03
# x-published: 2012-01-03T08:22:00
#
# v0.9	Initial Build – Hal
# V1.0	Added support for UDP, and processname -Glenn
# v1.1	Expanded [regex] statements to encompass IPV4/IPV6/ports. -Glenn
# v1.2	Added support for services, removed errors when no process could be found -HansO
#
Function Get-Netstat {
    $null, $null, $null, $null, $netstat = netstat -a -n -o
    [regex]$regexTCP = '(?<Protocol>\S+)\s+((?<LAddress>(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?))|(?<LAddress>\[?[0-9a-fA-f]{0,4}(\:([0-9a-fA-f]{0,4})){1,7}\%?\d?\]))\:(?<Lport>\d+)\s+((?<Raddress>(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?))|(?<RAddress>\[?[0-9a-fA-f]{0,4}(\:([0-9a-fA-f]{0,4})){1,7}\%?\d?\]))\:(?<RPort>\d+)\s+(?<State>\w+)\s+(?<PID>\d+$)'

    [regex]$regexUDP = '(?<Protocol>\S+)\s+((?<LAddress>(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?))|(?<LAddress>\[?[0-9a-fA-f]{0,4}(\:([0-9a-fA-f]{0,4})){1,7}\%?\d?\]))\:(?<Lport>\d+)\s+(?<RAddress>\*)\:(?<RPort>\*)\s+(?<PID>\d+)'

    [psobject]$process = "" | Select-Object Protocol, LocalAddress, Localport, RemoteAddress, Remoteport, State, PID, ProcessName, Services

    $Services = @{}
    get-wmiobject win32_service | ForEach-Object { 
        [String]$SvcPID = $_.processid
        If ($Services.ContainsKey($SvcPID))
        {
            $Services.Item($SvcPID) = $Services.Item($SvcPID) += $($_.Name)
        }
        Else
        {
            $Services.Add($SvcPID,@($_.Name))
        }
    }

    foreach ($net in $netstat)
    {
        switch -regex ($net.Trim())
        {
            $regexTCP
            {          
                $process.Protocol = $matches.Protocol
                $process.LocalAddress = $matches.LAddress
                $process.Localport = $matches.LPort
                $process.RemoteAddress = $matches.RAddress
                $process.Remoteport = $matches.RPort
                $process.State = $matches.State
                $process.PID = $matches.PID
                $process.ProcessName = ( Get-Process -Id $matches.PID -ea 0).ProcessName
                $process.Services = $Services.Item($matches.PID)
            }
            $regexUDP
            {          
                $process.Protocol = $matches.Protocol
                $process.LocalAddress = $matches.LAddress
                $process.Localport = $matches.LPort
                $process.RemoteAddress = $matches.RAddress
                $process.Remoteport = $matches.RPort
                $process.State = $matches.State
                $process.PID = $matches.PID
                $process.ProcessName = ( Get-Process -Id $matches.PID -ea 0).ProcessName
                $process.Services = $Services.Item($matches.PID)
            }
        }
    $process
    }
}
