Analyze-Packet

If you’ve been trying out the Get-Packet script you’ve seen that there is a great deal of information. I wanted an easy way to analyze the data so I put together a script called Analyze-Packet that will slice and dice a saved network trace and produce a summary report.

   1: Param([object]$sniff)
   2:  
   3: $activity="Analyzing network trace"
   4: Write-Progress -Activity $activity -status "Counting packets" -percentcomplete 1
   5: $count = "Total packet count: {0}" -f $sniff.count
   6:  
   7: Write-Progress -Activity $activity -status "Calculating elapsed time" -percentcomplete 5
   8: $elapsed = "Total elapsed time: {0}" -f ($sniff[-1].time -$sniff[0].time).ToString()
   9: #calculate packets per second
  10: $pps = $sniff.count/(($sniff[-1].time -$sniff[0].time).totalseconds)
  11: $pps="{0:N4}" -f $pps
  12: $packetsPerSecond="Packets per second: $pps"
  13:  
  14: Write-Progress -Activity $activity -status "Calculating protocol distribution" -percentcomplete 20
  15: $protocols = $sniff | sort protocol | group protocol | sort count -descending | select Count,@{name="Protocol";Expression={$_.name}} 
  16:  
  17: Write-Progress -Activity $activity -status "Building source list" -percentcomplete 30
  18: $sourcelist = $sniff | sort source | select Source
  19:  
  20: Write-Progress -Activity $activity -status "Calculating source distribution" -percentcomplete 35
  21: $ips = $sourcelist| group source |sort count -descending | select Count,Name
  22:  
  23: $sources=@()
  24:  
  25: #turn off errors to prevent the script from halting if an IP can't be resolved
  26: $errorActionPreference="SilentlyContinue"
  27:  
  28: for ($i=0;$i -lt $ips.count;$i++) { 
  29:     Write-Progress -Activity $activity -status "Resolving Source IP addresses" -currentoperation $ips[$i].name -percentcomplete (($i/$ips.count)*100)
  30:     
  31:     $obj=New-Object PSObject
  32:     $resolved=[system.Net.dns]::getHostEntry($ips[$i].Name).hostName
  33:  
  34:     if (!$resolved) {
  35:         $resolved="Not Found"
  36:         }
  37:     $obj | Add-Member -MemberType Noteproperty -name "Count" -value $ips[$i].Count
  38:     $obj | Add-Member -MemberType Noteproperty -name "IP" -value $ips[$i].name
  39:     $obj | Add-Member -MemberType Noteproperty -name "Host" -value $resolved
  40:     $sources+=$obj
  41: }
  42:  
  43: #turn error pipeline back on
  44: $errorActionPreference="Continue"
  45:     
  46: Write-Progress -Activity $activity -status "Calculating source port distribution" -percentcomplete 40
  47: $sourceport = $sniff | sort sourceport | group sourceport |sort count -descending | select Count,@{name="Port";Expression={$_.name}}
  48:  
  49: Write-Progress -Activity $activity -status "Calculating destination distribution" -percentcomplete 50
  50: $destinations = $sniff | sort destination | group destination | sort count -descending | select Count,@{name="IP";Expression={$_.name}}
  51:  
  52: Write-Progress -Activity $activity -status "Calculating destination port distribution" -percentcomplete 60
  53: $destinationport = $sniff | sort destport | group destport |sort count -descending | select Count,@{name="Port";Expression={$_.name}}
  54:  
  55: Write-Progress -Activity $activity -status "Presenting data" -Completed $True -percentcomplete 100
  56:  
  57: #write results
  58: write "NETWORK TRACE ANALYSIS"
  59: write ("-" * 50)
  60: write `t
  61: write $count
  62: write $elapsed
  63: write $packetsPerSecond
  64: write `t
  65: write "PROTOCOLS"
  66: $protocols | Select Count,Protocol,@{Name="Percentage";Expression={"{0:P4}" -f ($_.count/$sniff.count)}} 
  67: write "DESTINATION IP"
  68: $destinations | Select Count,IP,@{Name="Percentage";Expression={"{0:P4}" -f ($_.count/$sniff.count)}} 
  69: write "DESTINATION PORTS"
  70: $destinationport | select Count,Port,@{Name="Percentage";Expression={"{0:P4}" -f ($_.count/$sniff.count)}} 
  71: write "SOURCE IP"
  72: $sources | Select Count,IP,Host,@{Name="Percentage";Expression={"{0:P4}" -f ($_.count/$sniff.count)}} 
  73: write "SOURCE PORTS"
  74: $sourceport | Select Count,Port,@{Name="Percentage";Expression={"{0:P4}" -f ($_.count/$sniff.count)}} 
  75:  

The script takes a variable that holds the results of the Get-Packet script. I tried to come up with as many different views of the data as I could think of that might be relevant. There are break downs of packets by source ports, IP addresses and more. Because the analysis takes time, I used Write-Progress to provide feedback. This is a great cmdlet to use for long running tasks like this. Something else you might find useful from the script is code I use to resolve IP addresses to a host name using the System.Net.DNS class.

   1: $resolved=[system.Net.dns]::getHostEntry($ips[$i].Name).hostName 

I turned off the error pipeline because if the method failed to resolved an IP address, it produced an error that halted the script.

I recommend saving the results to a variable since this script may take several minutes or longer run depending on the size of your trace.

PS C:\> $report=c:\scripts\Analyze-packet.ps1 $sniff

Here’s a truncated sample of a report to give you an idea of what to expect. You could pipe $report to Out-File or Out-Printer. However, because it doesn’t output a single object it doesn’t lend itself to exporting or converting to an HTML file. I might come back to this at a later date and see if there are any alternatives. If you have suggestions, please let me know.