# encoding: ascii # api: powershell # title: SharpPcap # description: Your first steps at capturing packets from PowerShell with WinPcap via SharpPcap # version: 4.7 # type: script # author: Joel Bennett # license: CC0 # x-poshcode-id: 5374 # x-archived: 2014-08-24T13:26:44 # x-published: 2014-08-19T23:11:00 # # # First, you have to install WinPcap # http://www.winpcap.org/install/default.htm # Then, you have to download SharpPcap # http://sourceforge.net/projects/sharppcap/ # And you need to import the assembly from wherever you put it Add-Type -Path $SkyProfileDir\Libraries\SharpPcap*\SharpPcap.dll # To avoid crashing, you MUST avoid accessing the NonBlockingMode property # But I also want to expose the Interface.FriendlyName because it's the meaningful name Update-TypeData -TypeName SharpPcap.WinPcap.WinPcapDevice ` -MemberName FriendlyName -MemberType ScriptProperty -Value { $this.Interface.FriendlyName } Update-TypeData -TypeName SharpPcap.WinPcap.WinPcapDevice ` -DefaultDisplayProperty FriendlyName -DefaultDisplayPropertySet FriendlyName, Addresses, Description, MacAddress # The MacAddress property doesn't seem to work right now, but Interface.MacAddress does Update-TypeData -TypeName SharpPcap.WinPcap.WinPcapDevice ` -MemberName MacAddress -MemberType ScriptProperty -Value { $this.Interface.MacAddress } -Force # By default, PcapAddress ToString() shows the address and netmask etc. which we don't need to see all the time. Update-TypeData -TypeName SharpPcap.LibPcap.PcapAddress ` -DefaultDisplayProperty Addr -MemberName ToString -MemberType ScriptMethod -Value { $this.Addr.ToString() } -Force # Then you need to pick a device to capture with [SharpPcap.CaptureDeviceList]::Instance | Format-Table FriendlyName, Addresses, Description, MacAddress -Auto -Wrap # If the pipeline-enabled Read-Choice is available: Import-Module Reflection -Min 4.7 -ErrorAction SilentlyContinue if($choose = get-command Read-Choice* | ? { $_.Parameters.Values.GetEnumerator() | % Attributes | % ValueFromPipeline }) { $device = [SharpPcap.CaptureDeviceList]::Instance | &$choose -Prompt "Please choose a device for capture:" -Label FriendlyName -Passthru } else { $device = [SharpPcap.CaptureDeviceList]::Instance | Where { $_.Addresses.Addr -like "192.*" } | Select -First 1 } Get-EventSubscriber -Source $device.MacAddress -EA 0 | Where EventName -eq OnPacketArrival | Unregister-Event $null = Register-ObjectEvent $device -EventName OnPacketArrival -Source $device.MacAddress { try { # Do something useful with the CaptureEventArgs in $EventArgs: $Packet = [PacketDotNet.Packet]::ParsePacket($EventArgs.Packet.LinkLayerType, $EventArgs.Packet.Data) # If you just want the TcpPacket: # $Packet = $Packet.Extract([PacketDotNet.TcpPacket]) # If you want to see what you could be doing ... # $Packet | Get-Member | Out-String -Stream | % Trim | Write-Host # This isn't useful, but it's a nice demo Write-Host ([DateTime]$EventArgs.Packet.Timeval.Date) "Len=" $EventArgs.Packet.Data.Length -Foreground Cyan Write-Host $Packet.ToString() } catch { Write-Host "ERROR:" $_ -Foreground Red } } Write-Host "Capturing on" $device.FriendlyName $device.Open([SharpPcap.DeviceMode]::Promiscuous, 1000); # Receive only TCP packets $device.Filter = "tcp" $device.StartCapture() # Listen for a while ... # In order to make sure the "host" output of the event handler shows up ... # We should Write-Host on the current thread (ugh, that's screwy) for($msec=0; $msec -lt 3000; $msec += 100) { Start-Sleep -milli 100 Write-Host -NoNewLine } # Clean up $device.StopCapture() $device.Close()