# My Recent Powershell Modules

By
,
Powershell
,
Modules
Published 2022-07-16

TShark Module
https://www.powershellgallery.com/packages/TShark/1.0.2

#Windows Administrators 🐭

So I have found over the decades of working in IT that not many system administrators know how to code. Yeah they know how to google and copy and paste code, and run the script they found. But when it comes to modifying that code, it doesn't seem possible to that person, as they don't have a scooby-doo about what the code is doing, or how to read it. Most places I have worked only a very few people can actually code to solve a given problem. Due to the stress of certain jobs, you might find that the one person who can help is a bit like

An angry sysadmin coder
An angry sysadmin coder

#I needed a point and click 🐁

Yep I hate to admit it but this year I was trying to solve a complicated issue that had existed before I even started the job. On the plus side I knew it wasn't my fault, or I couldn't take the blame. However neither of those plus signs was going to solve the problem. Although I had know about the program for sometime, I hadn't had a real use-case for using WireShark. Before I knew it I had used WireShark to analyze a number of bizarre issues I had been gifted with to solve. Again this got me thinking why isn't there a Powershell equivalent of this program? I did a bit of training on the program through various sources and it was mentioned there is the command-line version TShark.exe which could also be used to take network captures.

#TShark for Powershell 🦈

TShark lets you hunt down network issues just like a real shark
TShark lets you hunt down network issues just like a real shark

First of all just incase you didn't know, but WireShark has a command line tool that allows you to capture a network trace file. Although this may not be as graphical as the GUI version, it does give you all the same functionality, and allows you to do cool things like starting a network capture, that will output in 50MB files and make 10 of these files then keep cycling through over-writing the oldest file, so you could keep a network trace running for a long time, without worrying about filling up the disk, or having a gigantic trace file at the end of it. This is just one of the many things you can do with TShark. One of the things I do not like about using certain command line tools, is the parameters they use sometimes make little to no sense, or they might just be a bit too much to remember. By re-building this command line tool TShark into a Powershell module I would be able to decide on the parameter names, and which parameters to include. The only downside to deciding to rebuild an application into a module using crescendo, is it will not include the program in the module. However a few lines of Powershell code that you can install WireShark which includes TShark:-

Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') scoop install git scoop bucket add extras scoop install wireshark

I have included the code above in the module as an additonal function, to allow you to automatically install the required software to use the module. This module is a function module, please look through the code to see what it does, as I did spend a good amount of time on the help for this module so that you could fully understand how to get a network trace easily from Powershell to then either diagnose in the shell or to open the captured trace file in WireShark.

# Module created by Microsoft.PowerShell.Crescendo class PowerShellCustomFunctionAttribute : System.Attribute { [bool]$RequiresElevation [string]$Source PowerShellCustomFunctionAttribute() { $this.RequiresElevation = $false; $this.Source = "Microsoft.PowerShell.Crescendo" } PowerShellCustomFunctionAttribute([bool]$rElevation) { $this.RequiresElevation = $rElevation $this.Source = "Microsoft.PowerShell.Crescendo" } } function Start-TShark { [PowerShellCustomFunctionAttribute(RequiresElevation=$False)] [CmdletBinding()] param( [Parameter()] [String]$SetInterface, [Parameter()] [String]$SetCaptureFilter, [Parameter()] [Switch]$SetDataLinkType, [Parameter()] [Switch]$GetInterfaces, [Parameter()] [Switch]$GetDataLinkTypes, [Parameter()] [String]$Path, [Parameter()] [ValidateSet("pcap","pcapng","5views","btsnoop","commview-ncf","commview-ncfx","dct2000","erf","eyesdn","k12text","lanalyzer","logcat","logcat-brief","logcat-long","logcat-process","logcat-tag","logcat-thread","logcat-threadtime","logcat-time","modpcap","netmon1","netmon2","nettl","ngsniffer","ngwsniffer_1_1","ngwsniffer_2_0","nokiapcap","nsecpcap","nstrace10","nstrace20","nstrace30","nstrace35","observer","rf5","rh6_1pcap","snoop","suse6_3pcap","visual")] [String]$SetFileType, [Parameter()] [String]$LogPath, [Parameter()] [ValidateScript( {if ($_ -match "filesize:[0-9]+$") { $true } else { throw 'use filesize: followed by number which represents KiloBytes Example:- filesize:1024 this will output 1mb capture files.' } })] [ArgumentCompleter( { param($cmd, $param, $wordToComplete) # This is the duplicated part of the code in the [ValidateScipt] attribute. [array] $validValues = [regex]"filesize:[0-9]+$" $validValues -like "$wordToComplete*" } )] [String]$SetFileCaptureSizeKB, [Parameter()] [ValidateScript( {if ($_ -match "duration:[0-9]+$") { $true } else { throw 'use duration: followed by number which represents seconds in time Example:- duration:60 this will output a capture files 60 seconds apart.' } })] [ArgumentCompleter( { param($cmd, $param, $wordToComplete) # This is the duplicated part of the code in the [ValidateScipt] attribute. [array] $validValues = [regex]"duration:[0-9]+$" $validValues -like "$wordToComplete*" } )] [String]$SetFileCaptureDuration, [Parameter()] [ValidateScript( {if ($_ -match "files:[0-9]+$") { $true } else { throw 'use files: followed by number which represents the number of 5 in total to capture Example:- files:10 this will output 10 capture files and then replace.' } })] [ArgumentCompleter( { param($cmd, $param, $wordToComplete) # This is the duplicated part of the code in the [ValidateScipt] attribute. [array] $validValues = [regex]"files:[0-9]+$" $validValues -like "$wordToComplete*" } )] [String]$SetNumberCaptureFiles, [Parameter()] [Switch]$GetVersion, [Parameter()] [String]$OpenFile, [Parameter()] [ValidateSet("expert","afp,srt","ancp,tree","ansi_a,bsmap","ansi_a,dtap","ansi_map","asap,stat","bacapp_instanceid,tree","bacapp_ip,tree","bacapp_objectid,tree","bacapp_service,tree","calcappprotocol,stat","camel,counter","camel,srt","collectd,tree","componentstatusprotocol,stat","conv,bluetooth","conv,dccp","conv,eth","conv,fc","conv,fddi","conv,ip","conv,ipv6","conv,ipx","conv,jxta","conv,mptcp","conv,ncp","conv,rsvp","conv,sctp","conv,sll","conv,tcp","conv,tr","conv,udp","conv,usb","conv,wlan","conv,wpan","conv,zbee_nwk","credentials","dcerpc,srt","dests,tree","dhcp,stat","diameter,avp","diameter,srt","dns,tree","endpoints,bluetooth","endpoints,dccp","endpoints,eth","endpoints,fc","endpoints,fddi","endpoints,ip","endpoints,ipv6","endpoints,ipx","endpoints,jxta","endpoints,mptcp","endpoints,ncp","endpoints,rsvp","endpoints,sctp","endpoints,sll","endpoints,tcp","endpoints,tr","endpoints,udp","endpoints,usb","endpoints,wlan","endpoints,wpan","endpoints,zbee_nwk","enrp,stat","expert","f1ap,tree","f5_tmm_dist,tree","f5_virt_dist,tree","fc,srt","flow,any","flow,icmp","flow,icmpv6","flow,lbm_uim","flow,tcp","follow,dccp","follow,http","follow,http2","follow,quic","follow,sip","follow,tcp","follow,tls","follow,udp","fractalgeneratorprotocol,stat","gsm_a","gsm_a,bssmap","gsm_a,dtap_cc","gsm_a,dtap_gmm","gsm_a,dtap_mm","gsm_a,dtap_rr","gsm_a,dtap_sacch","gsm_a,dtap_sm","gsm_a,dtap_sms","gsm_a,dtap_ss","gsm_a,dtap_tp","gsm_map,operation","gtp,srt","h225,counter","h225_ras,rtd","hart_ip,tree","hosts","hpfeeds,tree","http,stat","http,tree","http2,tree","http_req,tree","http_seq,tree","http_srv,tree","icmp,srt","icmpv6,srt","io,phs","io,stat","ip_hosts,tree","ip_srcdst,tree","ipv6_dests,tree","ipv6_hosts,tree","ipv6_ptype,tree","ipv6_srcdst,tree","isup_msg,tree","lbmr_queue_ads_queue,tree","lbmr_queue_ads_source,tree","lbmr_queue_queries_queue,tree","lbmr_queue_queries_receiver,tree","lbmr_topic_ads_source,tree","lbmr_topic_ads_topic,tree","lbmr_topic_ads_transport,tree","lbmr_topic_queries_pattern,tree","lbmr_topic_queries_pattern_receiver,tree","lbmr_topic_queries_receiver,tree","lbmr_topic_queries_topic,tree","ldap,srt","mac-lte,stat","megaco,rtd","mgcp,rtd","mtp3,msus","ncp,srt","ngap,tree","npm,stat","osmux,tree","pingpongprotocol,stat","plen,tree","proto,colinfo","ptype,tree","radius,rtd","rlc-lte,stat","rpc,programs","rpc,srt","rtp,streams","rtsp,stat","rtsp,tree","sametime,tree","scsi,srt","sctp,stat","sip,stat","smb,sids","smb,srt","smb2,srt","smpp_commands,tree","snmp,srt","ssprotocol,stat","sv","ucp_messages,tree","wsp,stat")] [String]$GetStatistics ) BEGIN { $__PARAMETERMAP = @{ SetInterface = @{ OriginalName = '-i' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } SetCaptureFilter = @{ OriginalName = '-f' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } SetDataLinkType = @{ OriginalName = '-y' OriginalPosition = '0' Position = '2147483647' ParameterType = 'Switch' ApplyToExecutable = $False NoGap = $False } GetInterfaces = @{ OriginalName = '-D' OriginalPosition = '0' Position = '2147483647' ParameterType = 'Switch' ApplyToExecutable = $False NoGap = $False } GetDataLinkTypes = @{ OriginalName = '-L' OriginalPosition = '0' Position = '2147483647' ParameterType = 'Switch' ApplyToExecutable = $False NoGap = $False } Path = @{ OriginalName = '-w' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } SetFileType = @{ OriginalName = '-F' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } LogPath = @{ OriginalName = '--log-file' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } SetFileCaptureSizeKB = @{ OriginalName = '-b' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } SetFileCaptureDuration = @{ OriginalName = '-b' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } SetNumberCaptureFiles = @{ OriginalName = '-b' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } GetVersion = @{ OriginalName = '-v' OriginalPosition = '0' Position = '2147483647' ParameterType = 'Switch' ApplyToExecutable = $False NoGap = $False } OpenFile = @{ OriginalName = '-r' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } GetStatistics = @{ OriginalName = '-z' OriginalPosition = '0' Position = '2147483647' ParameterType = 'String' ApplyToExecutable = $False NoGap = $False } } $__outputHandlers = @{ Default = @{ StreamOutput = $true; Handler = { $input } } } } PROCESS { $__boundParameters = $PSBoundParameters $__defaultValueParameters = $PSCmdlet.MyInvocation.MyCommand.Parameters.Values.Where({$_.Attributes.Where({$_.TypeId.Name -eq "PSDefaultValueAttribute"})}).Name $__defaultValueParameters.Where({ !$__boundParameters["$_"] }).ForEach({$__boundParameters["$_"] = get-variable -value $_}) $__commandArgs = @() $MyInvocation.MyCommand.Parameters.Values.Where({$_.SwitchParameter -and $_.Name -notmatch "Debug|Whatif|Confirm|Verbose" -and ! $__boundParameters[$_.Name]}).ForEach({$__boundParameters[$_.Name] = [switch]::new($false)}) if ($__boundParameters["Debug"]){wait-debugger} foreach ($paramName in $__boundParameters.Keys| Where-Object {!$__PARAMETERMAP[$_].ApplyToExecutable}| Sort-Object {$__PARAMETERMAP[$_].OriginalPosition}) { $value = $__boundParameters[$paramName] $param = $__PARAMETERMAP[$paramName] if ($param) { if ($value -is [switch]) { if ($value.IsPresent) { if ($param.OriginalName) { $__commandArgs += $param.OriginalName } } elseif ($param.DefaultMissingValue) { $__commandArgs += $param.DefaultMissingValue } } elseif ( $param.NoGap ) { $pFmt = "{0}{1}" if($value -match "\s") { $pFmt = "{0}""{1}""" } $__commandArgs += $pFmt -f $param.OriginalName, $value } else { if($param.OriginalName) { $__commandArgs += $param.OriginalName } $__commandArgs += $value | Foreach-Object {$_} } } } $__commandArgs = $__commandArgs | Where-Object {$_ -ne $null} if ($__boundParameters["Debug"]){wait-debugger} if ( $__boundParameters["Verbose"]) { Write-Verbose -Verbose -Message tshark.exe $__commandArgs | Write-Verbose -Verbose } $__handlerInfo = $__outputHandlers[$PSCmdlet.ParameterSetName] if (! $__handlerInfo ) { $__handlerInfo = $__outputHandlers["Default"] # Guaranteed to be present } $__handler = $__handlerInfo.Handler if ( $PSCmdlet.ShouldProcess("tshark.exe $__commandArgs")) { # check for the application and throw if it cannot be found if ( -not (Get-Command -ErrorAction Ignore "tshark.exe")) { throw "Cannot find executable 'tshark.exe'" } if ( $__handlerInfo.StreamOutput ) { & "tshark.exe" $__commandArgs | & $__handler } else { $result = & "tshark.exe" $__commandArgs & $__handler $result } } } # end PROCESS <# .SYNOPSIS This is allowing you to run TShark.exe in powershell using powershell .DESCRIPTION Inspired by Adam Driscoll and the Sysinternals module I wanted to do something similar so bringing tshark to powershell. Although this module does not at the moment include every single parameter tshark does, I still think it was worth bringing this to powershell to act as another tool for the sysadmins tool-kit you have. I like hanging out in my shell all day so this now allows me to easily use tshark from Powershell .PARAMETER SetInterface This is the same as the -i parameter in tshark but with a more helpful paramter name I think. So this will set the name of the network interface to use for live packet capture. Please note to get a list of YOUR valid network interfaces use the -GetInterface paramter first. .PARAMETER SetCaptureFilter Set the capture filter expression using wireshark syntax, to only filter on dns just simply type dns after this parameter name. Please do not use this if you are un-sure of the syntax, you can always filter the capture file in the wireshark GUI after the capture is complete. .PARAMETER SetDataLinkType Set the data link type to use while capturing packets. The values reported by -GetDataLinkTypes are the values that can be used as the value for this parameter .PARAMETER GetInterfaces Print a list of the interfaces on which TShark can capture, and exit. For each network interface, a number and an interface name, possibly followed by a text description of the interface, is printed. The interface name or the number can be supplied to the -SetInterface option to specify an interface on which to capture. .PARAMETER GetDataLinkTypes List the data link types supported by the interface and exit. The reported link types can be used with the -SetDataLinkTypes parameter .PARAMETER Path Type the full file output path you want the file to go to including the file name and file extension. For example:- -Path C:\Users\MyAccount\MyCapture.pcapng .PARAMETER SetFileType This allows you to see all the possible file extension output types. So you can select a different output to the default pcapng format should you so wish to. Please remember to also specify this in the -Path value the parameter file-type extension you selected .PARAMETER LogPath This will allow you to specify a .txt or .log file to output messages to that appear on the screen during the capture .PARAMETER SetFileCaptureSizeKB This is using the capture ring buffer option from tshark -b and using this to set the file size for the capture you wish to perform. After using this parameter name press TAB to auto-complete the parameter validation pattern .PARAMETER SetFileCaptureDuration This is using the capture ring buffer option from tshark -b this will set the amount of time in seconds that the capture is taken for to a file before going to the next file. After using this parameter name press TAB to auto-complete the parameter validation pattern .PARAMETER SetNumberCaptureFiles This is using the capture ring buffer option from tshark -b allowing you to set the number of rotating capture files you wish to capture. You would use this parameter in with either the -SetFileCaptureSizeKB or -SetFileCaptureDuration to allow you to fix the amount of files to store in the output directory. This will allow you to keep a trace running for days without flooding the hard drive full of data. After using this parameter name press TAB to auto-complete the parameter validation pattern .PARAMETER GetVersion This will display the current version of tshark you are using in the background to perform the task at hand. .PARAMETER OpenFile Allows you to display a capture file within the Powershell window you have open, should you wish to do some quick analysis on the capture .PARAMETER GetStatistics This allows you to choose from a large choice of statistics to display after it has opened the capture file. This is very useful to gain certain insights or to just get the expert statistics .EXAMPLE Start-TShark -Path C:\Zelda.pcapng -SetFileCaptureSizeKB filesize:10240 -SetNumberCaptureFiles files:10 This will output a rotating set of 10 files which will be 10MB in size. Pressing CTRL+C to exit the capture after the desired issue has been captured .EXAMPLE Start-TShark -SetInterface "Wi-Fi" -Path C:\DnsOutput.pcapng -LogPath C:\DnsOutput.txt This will being a capture on the Wi-Fi network interface, outputting to a .pcapng file and also record the output from messages on the Powershell screen to the log file specified in the -LogPath this file capture will continue to capture information until CTRL+C is pressed to stop the capture .EXAMPLE Start-TShark -OpenFile C:\SlowNetwork.pcapng -GetStatistics expert Will open the capture file specified in the -OpenFile parameter, this will also then provide you with the expert analysis information by specifying that value from the pre-defined list of choices on the -GetStatistics parameter .FUNCTIONALITY To use when you have a weird network issue you have been told to fix, allowing you to collect packet information to analyze in Wireshark #> } Function Install-TShark { if (Test-Path "$env:USERPROFILE\scoop") { Write-Host -ForegroundColor Yellow "Awesome it looks like you have scoop installed, checking to see if TShark present." if (Test-Path "$env:USERPROFILE\scoop\shims\tshark.exe") { Write-Host -ForegroundColor Yellow "It appears you have TShark installed you are all good to use Start-TShark now" } else { scoop install wireshark } } else { Write-Host -ForegroundColor Yellow "I am now installing scoop for you and TShark, then you can use Start-TShark once complete." Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') scoop install git scoop bucket add extras scoop install wireshark Write-Host -ForegroundColor Yellow "All done have a great day." } }

#Examples 👆

If you look at the bottom of the above code I did include a help file for this module, and a couple of examples of how to use this program. Once again please remember this module does not install the software automatically, although it does include a function to do this automatically for you after you have downloaded the module.

#I hope this helps you 🌱

So if you find yourself with a pickle of a problem to solve and know it could be network related, then give this tool a chance to find that issue for you. I really hope you enjoyed reading the about the first recent module I released and how this could potentially help you solve a complex problem 😁