├── README.md ├── docs ├── capture_usage │ ├── basic_usage.md │ ├── file_capture_usage.md │ └── live_capture_usage.md ├── css │ └── custom.css ├── decoding │ └── decode_packets.md ├── index.md ├── installation.md ├── js │ ├── copy-code.js │ ├── custom.js │ ├── highlight-init.js │ └── highlight.min.js ├── license.md ├── packet_layers.md ├── parameters │ ├── file_capture_parameters.md │ ├── inmem_capture_parameters.md │ ├── live_capture_parameters.md │ ├── livering_capture_parameters.md │ ├── pipe_capture_parameters.md │ └── remote_capture_parameters.md ├── parsing │ ├── eth_packets.md │ ├── ip_packets.md │ ├── tcp_packets.md │ └── udp_packets.md └── requirements.txt ├── examples ├── async_operations.py ├── dns_filtering_examples.py ├── frame_filtering_example.py ├── ftp_filtering_examples.py ├── https_filtering_examples.py ├── ip_filtering_examples.py └── snmp_filtering_examples.py ├── graphic └── binary_funnel.jpg ├── mkdocs.yml ├── pcap_files ├── http2-h2c.pcap └── traffic_flows_small.pcap ├── pyshark_packet_analysis.py └── readthedocs.yaml /README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 |

4 | This repository contains usage documentation for the Python module PyShark. This Python module is a wrapper for TShark, which is command-line interface (CLI) for Wireshark. The latter is used to sniff and capture packets from a network interface. The real power of PyShark is its capability to access all of the packet decoders built into TShark. 5 |

6 | 7 |

8 | This repository also contains some basic parsing examples, which are also contained in the usage documentation that I developed for PyShark. 9 |

10 | 11 | 12 | # LiveCapture Usage examples 13 | 14 | ## Basic Capture 15 | 16 | ```python 17 | import pyshark 18 | 19 | # Create a LiveCapture object to capture packets from the specified interface 20 | capture = pyshark.LiveCapture(interface='your capture interface') 21 | for packet in capture: 22 | # do something with the packet 23 | ``` 24 | 25 | ## LiveCapture with packet count 26 | 27 |

28 | 29 | PyShark LiveCapture has a featured named sniff_continuously that allows you to limit the number of packets captured. 30 | 31 |

32 | 33 | ```python 34 | import pyshark 35 | 36 | # Create a LiveCapture object to capture packets from the specified interface 37 | capture = pyshark.LiveCapture(interface='your capture interface') 38 | 39 | # Start capturing packets for a specified number of packets 40 | for packet in capture.sniff_continuously(packet_count=10): 41 | # do something with the packet 42 | ``` 43 | 44 | ## LiveCapture with timeout 45 | 46 |

47 | PyShark LiveCapture also has a featured named sniff that allows you to set a capture timeout period. 48 |

49 | 50 | ```python 51 | import pyshark 52 | 53 | # Create a LiveCapture object to capture packets from the specified interface 54 | capture = pyshark.LiveCapture(interface='your capture interface') 55 | 56 | # Start capturing packets for a specified duration (in seconds) 57 | capture.sniff(timeout=10) 58 | 59 | packets = [pkt for pkt in capture._packets] 60 | capture.close() 61 | for packet in packets: 62 | # do something with the packet 63 | ``` 64 | 65 | ## LiveCapture with BPF_Filter 66 | 67 |

68 | The PyShark LiveCapture mode has a BPF_Filter that allows you to prefilter the packets being captured. The example below show how to parse Domain Name System (DNS) packets from a LiveCapture session. 69 |

70 | 71 | ```python 72 | import pyshark 73 | 74 | # Create a LiveCapture object to capture packets from the specified interface with a bpf_filter 75 | capture = pyshark.LiveCapture(interface='your capture interface', bpf_filter='udp port 53') 76 | for packet in capture: 77 | # do something with the packet 78 | ``` 79 | 80 | ## LiveCapture with Display_Filter 81 | 82 |

83 | The PyShark LiveCapture mode has a Display_Filter that allows you to prefilter the packets being captured. The example below show how to parse Domain Name System (DNS) packets from a LiveCapture session. 84 |

85 | 86 | ```python 87 | import pyshark 88 | 89 | # Create a LiveCapture object to capture packets from the specified interface with a display_filter 90 | capture = pyshark.LiveCapture(interface='your capture interface', display_filter='dns') 91 | for packet in capture: 92 | # do something with the packet 93 | ``` 94 | 95 | # Additional parsing examples 96 | 97 |

98 | 99 | Here are some additional parsing examples within this repository. 100 | 101 |

102 | 103 | * Extract DNS elements from a PCAP packet 104 | 105 | * Extract FTP elements from a PCAP packet 106 | 107 | * Extract FRAME elements from a PCAP packet 108 | 109 | * Extract HTTPS/TLS elements from a PCAP packet 110 | 111 | * Filter PCAP packet based on Source or Destination 112 | 113 | * Extract SNMP elements from a PCAP packet 114 | 115 | * Asyncio programming with PyShark 116 | 117 |

118 | 119 | Here are some additional parsing examples that I posted to GitHub Gist. 120 | 121 |

122 | 123 | * Extract the conversation header information from a PCAP packet 124 | 125 | * Extract DNS elements from a PCAP packet 126 | 127 | * Extract the HTTP information from IPv4 and ICMPv6 packets 128 | 129 | * Extract specific IPv6 elements from a PCAP packet 130 | 131 | 132 | # Stack Overflow answers 133 | 134 |

135 | 136 | Here are some Stack Overflow answers that I posted for questions about PyShark. 137 | 138 |

139 | 140 | 141 | # Prerequisites 142 | 143 |

144 | 145 | TShark has to be installed and accessible via your $PATH, which Python queries for PyShark. Reference the installation section of the usage documentation for details on how to install TShark. 146 | 147 |

148 | 149 | # References 150 | 151 | * [PyShark:](https://kiminewt.github.io/pyshark)   Is the Python. wrapper for TShark., that allows Python. packet parsing using Wireshark. dissectors. 152 | 153 | * [TShark:](https://www.wireshark.org/docs/man-pages/tshark.html)   TShark. is a terminal oriented version of Wireshark. designed for capturing and displaying packets when an interactive user interface isn't necessary or available. 154 | 155 | * [Wireshark:](https://www.wireshark.org)   Wireshark is a network packet analysis tool that captures packets in real time and displays them in a graphic interface. 156 | 157 | * [Homebrew:](https://brew.sh)   Package Manager for macOS and Linux. 158 | 159 | * [Berkeley Packet Filter (BPF) syntax](https://biot.com/capstats/bpf.html) 160 | 161 | * [Display Filter syntax](https://wiki.wireshark.org/DisplayFilters) 162 | 163 | # Notes 164 | 165 |

166 | 167 | PyShark has limited documentation, so that is the reason why I developed the PyShark usage documentation within this repository for others to use. 168 | 169 |

170 | 171 | _The code within this repository is **not** production ready. It was **strictly** designed for experimental testing purposes only._ 172 | -------------------------------------------------------------------------------- /docs/capture_usage/basic_usage.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Basic Usage

4 | 5 |
6 | 7 |

8 | 9 | PyShark has several capture modes to process and dissect packet data. These modes are FileCapture, LiveCapture, RemoteCapture, InMemCapture and PipeCapture. Each capture mode has various filters that can be applied to the packets being collected. 10 | 11 |

12 | 13 | 14 | ### FileCapture Usage 15 | 16 |

17 | 18 | FileCapture is designed to read and process data from a packet capture (PCAP) file. 19 | 20 |

21 | 22 | 23 | ```python 24 | 25 | import pyshark 26 | 27 | capture = pyshark.FileCapture(input_file='your pcap file') 28 | for packet in capture: 29 | # do something with the packet 30 | 31 | ``` 32 | 33 | ### LiveCapture Usage 34 | 35 |

36 | 37 | LiveCapture is designed to perform a live capture from a network interface. 38 | 39 |

40 | 41 | ```python 42 | import pyshark 43 | 44 | capture = pyshark.LiveCapture(interface='your capture interface') 45 | for packet in capture: 46 | # do something with the packet 47 | 48 | ``` 49 | 50 | 51 | ### RemoteCapture Usage 52 | 53 |

54 | 55 | RemoteCapture is designed to perform a live capture from a network interface on a remote machine which has a rpcapd service running. 56 | 57 |

58 | 59 | 60 | ```python 61 | import pyshark 62 | 63 | capture = pyshark.RemoteCapture(remote_host='192.168.1.1', remote_interface='eth0') 64 | for packet in capture: 65 | # do something with the packet 66 | ``` 67 | 68 | ### LiveRingCapture Usage 69 | 70 | 71 |

72 | 73 | LiveRingCapture is designed to perform a live capture from a network interface. 74 | 75 |

76 | 77 | ```python 78 | import pyshark 79 | 80 | capture = pyshark.LiveRingCapture(interface='your capture interface') 81 | for packet in capture: 82 | # do something with the packet 83 | 84 | ``` 85 | 86 | ### InMemCapture Usage 87 | 88 |

89 | 90 | InMemCapture is designed to perform a live capture directly in memory instead of saving them to a file. 91 | This capture method can be useful for real-time packet analysis or when you want to process packets as soon as they are captured. 92 | 93 |

94 | 95 | 96 | ```python 97 | import pyshark 98 | 99 | capture = pyshark.InMemCapture() 100 | for packet in capture: 101 | # do something with the packet 102 | 103 | ``` 104 | 105 | 106 | ### PipeCapture Usage 107 | 108 |

109 | 110 | PipeCapture is designed to perform a capture from a named pipe rather than directly from a network interface or a file. A named pipe is a special file that is used to transfer data between unrelated processes. 111 | 112 | Here is a Microsoft reference on named pipes. 113 | 114 |

115 | 116 | 117 | ```python 118 | import pyshark 119 | 120 | capture = pyshark.PipeCapture(pipe='your pipe path') 121 | for packet in capture: 122 | # do something with the packet 123 | 124 | ``` 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /docs/capture_usage/file_capture_usage.md: -------------------------------------------------------------------------------- 1 |

FileCapture Usage

2 | --- 3 | 4 |

5 | 6 | FileCapture is designed to query a Packet Capture (PCAP) file. This mode has various filters that can be applied to the packets being processed. 7 | 8 |

9 | 10 | 11 | ### FileCapture basic usage 12 | 13 | 14 | ```python 15 | 16 | import pyshark 17 | 18 | capture = pyshark.FileCapture(input_file='your pcap file') 19 | for packet in capture: 20 | # do something with the packet 21 | 22 | ``` 23 | 24 | ### FileCapture with bpf_filter 25 | 26 |

27 | 28 | FileCapture has a featured named BPF_Filter (Berkeley Packet Filter) that allows you to prefilter the packets being captured. The example below show how to parse Domain Name System (DNS) packets from a FileCapture session. 29 | 30 |

31 | 32 | ```python 33 | 34 | import pyshark 35 | 36 | capture = pyshark.FileCapture(input_file='your pcap file', bpf_filter='udp port 53') 37 | for packet in capture: 38 | # do something with the packet 39 | 40 | ``` 41 | 42 | ### FileCapture with display_filter 43 | 44 |

45 | 46 | FileCapture has a featured named display_filter that allows you to prefilter the packets being captured. The example below show how to parse Domain Name System (DNS) packets using display_filter from a FileCapture session. 47 | 48 |

49 | 50 | ```python 51 | 52 | import pyshark 53 | 54 | capture = pyshark.FileCapture(input_file='your pcap file', display_filter='dns') 55 | for packet in capture: 56 | # do something with the packet 57 | 58 | ``` 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /docs/capture_usage/live_capture_usage.md: -------------------------------------------------------------------------------- 1 |

LiveCapture Usage

2 | --- 3 | 4 |

5 | 6 | LiveCapture is designed to perform a live capture from a network interface. This mode has various filters that can be applied to the packets being collected and processed. 7 | 8 |

9 | 10 | 11 | ### LiveCapture basic usage 12 | 13 | 14 | ```python 15 | 16 | import pyshark 17 | 18 | capture = pyshark.LiveCapture(interface='your capture interface') 19 | for packet in capture: 20 | # do something with the packet 21 | 22 | ``` 23 | 24 | ### LiveCapture with packet count 25 | 26 |

27 | 28 | LiveCapture has a featured named sniff_continuously that allows you to limit the number of packets captured. 29 | 30 |

31 | 32 | 33 | ```python 34 | 35 | import pyshark 36 | 37 | capture = pyshark.LiveCapture(interface='your capture interface') 38 | for packet in capture.sniff_continuously(packet_count=10): 39 | # do something with the packet 40 | 41 | ``` 42 | 43 | ### LiveCapture with timeout 44 | 45 |

46 | 47 | LiveCapture has a featured named sniff that allows you to set a capture timeout period. 48 | 49 |

50 | 51 | ```python 52 | 53 | import pyshark 54 | 55 | capture = pyshark.LiveCapture(interface='your capture interface') 56 | capture.sniff(timeout=10) 57 | packets = [pkt for pkt in capture._packets] 58 | capture.close() 59 | for packet in packets: 60 | # do something with the packet 61 | 62 | ``` 63 | 64 | ### LiveCapture with bpf_filter 65 | 66 |

67 | 68 | LiveCapture has a featured named BPF_Filter (Berkeley Packet Filter) that allows you to prefilter the packets being captured. The example below show how to parse Domain Name System (DNS) packets from a LiveCapture session. 69 | 70 |

71 | 72 | ```python 73 | 74 | import pyshark 75 | 76 | capture = pyshark.LiveCapture(interface='your capture interface', bpf_filter='udp port 53') 77 | for packet in capture: 78 | # do something with the packet 79 | 80 | ``` 81 | 82 | ### LiveCapture with display_filter 83 | 84 |

85 | 86 | LiveCapture has a featured named display_filter that allows you to prefilter the packets being captured. The example below show how to parse Domain Name System (DNS) packets using display_filter from a LiveCapture session. 87 | 88 |

89 | 90 | ```python 91 | 92 | import pyshark 93 | 94 | capture = pyshark.LiveCapture(interface='your capture interface', display_filter='dns') 95 | for packet in capture: 96 | # do something with the packet 97 | 98 | ``` 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/css/custom.css: -------------------------------------------------------------------------------- 1 | hr { 2 | height: 1px; 3 | border-width:0; 4 | color:grey; 5 | background-color: grey; 6 | } 7 | 8 | .code-block-container { 9 | background-color: #f7f4ef 10 | color: #ffffff; 11 | position: relative; 12 | display: inline-block; 13 | width: 100%; 14 | } 15 | 16 | .code-block { 17 | background-color: #2e2e2e; 18 | border: 1px solid #ddd; 19 | padding: 10px; 20 | border-radius: 5px; 21 | margin: 0; /* Remove default margin */ 22 | font-size: 14px; /* Adjust font size */ 23 | white-space : pre-wrap !important; 24 | word-break: break-word; 25 | overflow-wrap: break-word; /* Add for better compatibility */ 26 | overflow: auto; /* Add scrollbars if needed */ 27 | } 28 | 29 | .copy-btn { 30 | position: absolute; 31 | top: 5px; 32 | right: 5px; 33 | background-color: #EAF2F8; 34 | border: 1px solid #ddd; 35 | border-radius: 3px; 36 | padding: 5px 10px; 37 | cursor: pointer; 38 | display: flex; 39 | align-items: center; 40 | gap: 5px; 41 | font-size: 12px; /* Adjust font size */ 42 | } 43 | 44 | .copy-btn svg { 45 | width: 16px; 46 | height: 16px; 47 | } 48 | -------------------------------------------------------------------------------- /docs/decoding/decode_packets.md: -------------------------------------------------------------------------------- 1 |

Decoding Packets

2 | 3 | --- 4 | 5 | 6 |

7 | 8 | PyShark has a lot of flexibility to parse various types of information from an individual network packet. Some of this information can decoded into a more human readable form. Below are some examples of decoding specific information within packets. 9 | 10 |

11 | 12 | #### Decoding TCP packets used for Telnet 13 | 14 | 15 | ```python 16 | import pyshark 17 | 18 | capture_file = os.path.abspath(r'telnet-raw.pcap') 19 | capture = pyshark.FileCapture(input_file=capture_file) 20 | for packet in capture: 21 | try: 22 | if hasattr(packet, 'tcp') and 'TELNET' in str(packet.layers): 23 | payload = packet.tcp.payload 24 | print(f'TCP payload: {payload}') 25 | hex_split = payload.split(':') 26 | hex_as_chars = map(lambda hex: chr(int(hex, 16)), hex_split) 27 | human_readable = ''.join(hex_as_chars) 28 | print(f'Decoded payload: {human_readable}') 29 | except AttributeError as error: 30 | pass 31 | 32 | 33 | ``` 34 | 35 | Output: 36 | 37 | ```plaintext 38 | 39 | TCP payload: 6c:6f:67:69:6e:3a:20 40 | Decoded payload: login: 41 | 42 | truncated... 43 | 44 | TCP payload: 50:61:73:73:77:6f:72:64:3a 45 | Decoded payload: Password: 46 | 47 | truncated... 48 | 49 | TCP payload: 50:49:4e:47:20:77:77:77:2e:79:61:68:6f:6f:2e:63:6f:6d:20:28:32:30:34:2e:37:31:2e:32:30:30:2e:37:34:29:3a:20:35:36:20:64:61:74:61:20:62:79:74:65:73:0d:0a 50 | Decoded payload: PING www.yahoo.com (204.71.200.74): 56 data bytes 51 | 52 | 53 | ``` -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | 2 |

PyShark Documentation

3 |
4 | 5 |

Description

6 | 7 |

8 | This Read the Docs site is the usage documentation for the Python package PyShark. This documentation is a supplementary resource, with a huge amount of information that is not covered in the extended documentation for PyShark. 9 |

10 | 11 |

12 | PyShark is a Python 3 wrapper for TShark. Tshark is a network protocol analyzer that allows you to capture packet data from a live network, or read packets from a previously saved capture file. Tshark itself is the command-line version of Wireshark and PyShark allows Python packet parsing using Wireshark dissectors. 13 |

14 | 15 | 16 | ### PyShark use cases 17 | 18 |

19 | 20 | There are multiple use cases for PyShark. And these use cases can highly depend on the role of the person using PyShark. For example a network engineer might use PyShark to troubleshooting latency issues, while a security engineer might use PyShark to identify unauthorized data exfiltration. PyShark can perform these use cases in either real-time or in a post-mortem fashion. 21 |
22 |
23 | Below are some of the most common use cases. 24 | 25 |

26 | 27 | #### Common use cases 28 | 29 | -------------------------------------------------------------------------------- /docs/installation.md: -------------------------------------------------------------------------------- 1 | 2 |

PyShark Installation

3 | 4 | --- 5 | 6 |

Installation Overview

7 | 8 |

9 | 10 | There are multiple ways to install PyShark on systems running Microsoft Windows, Apple macOS or various flavors of Linux. An installation of TShark is also required for PyShark to function correctly. TShark is the command-line interface (CLI) tool from Wireshark. In most cases it is beneficial to install Wireshark, which includes TShark. The binaries for Wireshark are here. 11 |

12 | 13 | 14 |

PIP Installation Procedures

15 | 16 | ``` 17 | pip install pyshark 18 | 19 | ``` 20 |

21 | Use the following pip command to see the dependencies for PyShark prior to installing the package. 22 |

23 | 24 | ``` 25 | pip install --dry-run pyshark 26 | ``` 27 | 28 |

Brew Installation Procedures

29 | 30 | ``` 31 | brew install --cask wireshark 32 | 33 | ``` 34 | 35 |

36 | On Apple macOS systems ChmodBPF is also required to interact for network interfaces. 37 |

38 | 39 | ``` 40 | brew install --cask wireshark-chmodbpf 41 | 42 | ``` 43 | 44 |

45 | Use the following brew command to see the dependencies for Wireshark prior to installing the package. 46 |

47 | 48 | ``` 49 | brew deps --tree wireshark 50 | ``` 51 | -------------------------------------------------------------------------------- /docs/js/copy-code.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | document.querySelectorAll('pre code').forEach(function (block) { 3 | const button = document.createElement('button'); 4 | button.className = 'copy-btn'; 5 | button.innerHTML = ' Copy Code'; 6 | block.parentNode.insertBefore(button, block); 7 | 8 | button.addEventListener('click', function () { 9 | const code = block.innerText; 10 | navigator.clipboard.writeText(code).then(() => { 11 | button.textContent = 'Code Copied'; 12 | setTimeout(() => { 13 | button.innerHTML = ' Copy Code'; 14 | }, 2000); 15 | }).catch(err => { 16 | console.error('Failed to copy code:', err); 17 | }); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /docs/js/custom.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | var clipboard = new ClipboardJS('.copy-btn', { 3 | target: function (trigger) { 4 | return trigger.parentElement.querySelector('code'); 5 | } 6 | }); 7 | 8 | clipboard.on('success', function (e) { 9 | e.clearSelection(); 10 | alert('Code copied to clipboard'); 11 | }); 12 | 13 | clipboard.on('error', function (e) { 14 | alert('Failed to copy code'); 15 | }); 16 | }); -------------------------------------------------------------------------------- /docs/js/highlight-init.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', (event) => { 2 | document.querySelectorAll('pre code').forEach((block) => { 3 | hljs.highlightElement(block); 4 | }); 5 | }); -------------------------------------------------------------------------------- /docs/js/highlight.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Highlight.js v11.9.0 (git: b7ec4bfafc) 3 | (c) 2006-2024 undefined and other contributors 4 | License: BSD-3-Clause 5 | */ 6 | var hljs=function(){"use strict";function e(t){ 7 | return t instanceof Map?t.clear=t.delete=t.set=()=>{ 8 | throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{ 9 | throw Error("set is read-only") 10 | }),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{ 11 | const i=t[n],s=typeof i;"object"!==s&&"function"!==s||Object.isFrozen(i)||e(i) 12 | })),t}class t{constructor(e){ 13 | void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} 14 | ignoreMatch(){this.isMatchIgnored=!0}}function n(e){ 15 | return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") 16 | }function i(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] 17 | ;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const s=e=>!!e.scope 18 | ;class o{constructor(e,t){ 19 | this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ 20 | this.buffer+=n(e)}openNode(e){if(!s(e))return;const t=((e,{prefix:t})=>{ 21 | if(e.startsWith("language:"))return e.replace("language:","language-") 22 | ;if(e.includes(".")){const n=e.split(".") 23 | ;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") 24 | }return`${t}${e}`})(e.scope,{prefix:this.classPrefix});this.span(t)} 25 | closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ 26 | this.buffer+=``}}const r=(e={})=>{const t={children:[]} 27 | ;return Object.assign(t,e),t};class a{constructor(){ 28 | this.rootNode=r(),this.stack=[this.rootNode]}get top(){ 29 | return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ 30 | this.top.children.push(e)}openNode(e){const t=r({scope:e}) 31 | ;this.add(t),this.stack.push(t)}closeNode(){ 32 | if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ 33 | for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} 34 | walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ 35 | return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), 36 | t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ 37 | "string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ 38 | a._collapse(e)})))}}class c extends a{constructor(e){super(),this.options=e} 39 | addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){ 40 | this.closeNode()}__addSublanguage(e,t){const n=e.root 41 | ;t&&(n.scope="language:"+t),this.add(n)}toHTML(){ 42 | return new o(this,this.options).value()}finalize(){ 43 | return this.closeAllNodes(),!0}}function l(e){ 44 | return e?"string"==typeof e?e:e.source:null}function g(e){return h("(?=",e,")")} 45 | function u(e){return h("(?:",e,")*")}function d(e){return h("(?:",e,")?")} 46 | function h(...e){return e.map((e=>l(e))).join("")}function f(...e){const t=(e=>{ 47 | const t=e[e.length-1] 48 | ;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} 49 | })(e);return"("+(t.capture?"":"?:")+e.map((e=>l(e))).join("|")+")"} 50 | function p(e){return RegExp(e.toString()+"|").exec("").length-1} 51 | const b=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ 52 | ;function m(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n 53 | ;let i=l(e),s="";for(;i.length>0;){const e=b.exec(i);if(!e){s+=i;break} 54 | s+=i.substring(0,e.index), 55 | i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+(Number(e[1])+t):(s+=e[0], 56 | "("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)} 57 | const E="[a-zA-Z]\\w*",x="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",y="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",_="\\b(0b[01]+)",O={ 58 | begin:"\\\\[\\s\\S]",relevance:0},v={scope:"string",begin:"'",end:"'", 59 | illegal:"\\n",contains:[O]},k={scope:"string",begin:'"',end:'"',illegal:"\\n", 60 | contains:[O]},N=(e,t,n={})=>{const s=i({scope:"comment",begin:e,end:t, 61 | contains:[]},n);s.contains.push({scope:"doctag", 62 | begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", 63 | end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) 64 | ;const o=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) 65 | ;return s.contains.push({begin:h(/[ ]+/,"(",o,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s 66 | },S=N("//","$"),M=N("/\\*","\\*/"),R=N("#","$");var j=Object.freeze({ 67 | __proto__:null,APOS_STRING_MODE:v,BACKSLASH_ESCAPE:O,BINARY_NUMBER_MODE:{ 68 | scope:"number",begin:_,relevance:0},BINARY_NUMBER_RE:_,COMMENT:N, 69 | C_BLOCK_COMMENT_MODE:M,C_LINE_COMMENT_MODE:S,C_NUMBER_MODE:{scope:"number", 70 | begin:y,relevance:0},C_NUMBER_RE:y,END_SAME_AS_BEGIN:e=>Object.assign(e,{ 71 | "on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ 72 | t.data._beginMatch!==e[1]&&t.ignoreMatch()}}),HASH_COMMENT_MODE:R,IDENT_RE:E, 73 | MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+x,relevance:0}, 74 | NUMBER_MODE:{scope:"number",begin:w,relevance:0},NUMBER_RE:w, 75 | PHRASAL_WORDS_MODE:{ 76 | begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ 77 | },QUOTE_STRING_MODE:k,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/, 78 | end:/\/[gimuy]*/,contains:[O,{begin:/\[/,end:/\]/,relevance:0,contains:[O]}]}, 79 | RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", 80 | SHEBANG:(e={})=>{const t=/^#![ ]*\// 81 | ;return e.binary&&(e.begin=h(t,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:t, 82 | end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, 83 | TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_IDENT_RE:x, 84 | UNDERSCORE_TITLE_MODE:{scope:"title",begin:x,relevance:0}});function A(e,t){ 85 | "."===e.input[e.index-1]&&t.ignoreMatch()}function I(e,t){ 86 | void 0!==e.className&&(e.scope=e.className,delete e.className)}function T(e,t){ 87 | t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", 88 | e.__beforeBegin=A,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, 89 | void 0===e.relevance&&(e.relevance=0))}function L(e,t){ 90 | Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function B(e,t){ 91 | if(e.match){ 92 | if(e.begin||e.end)throw Error("begin & end are not supported with match") 93 | ;e.begin=e.match,delete e.match}}function P(e,t){ 94 | void 0===e.relevance&&(e.relevance=1)}const D=(e,t)=>{if(!e.beforeMatch)return 95 | ;if(e.starts)throw Error("beforeMatch cannot be used with starts") 96 | ;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] 97 | })),e.keywords=n.keywords,e.begin=h(n.beforeMatch,g(n.begin)),e.starts={ 98 | relevance:0,contains:[Object.assign(n,{endsParent:!0})] 99 | },e.relevance=0,delete n.beforeMatch 100 | },H=["of","and","for","in","not","or","if","then","parent","list","value"],C="keyword" 101 | ;function $(e,t,n=C){const i=Object.create(null) 102 | ;return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((n=>{ 103 | Object.assign(i,$(e[n],t,n))})),i;function s(e,n){ 104 | t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") 105 | ;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){ 106 | return t?Number(t):(e=>H.includes(e.toLowerCase()))(e)?0:1}const z={},W=e=>{ 107 | console.error(e)},X=(e,...t)=>{console.log("WARN: "+e,...t)},G=(e,t)=>{ 108 | z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0) 109 | },K=Error();function F(e,t,{key:n}){let i=0;const s=e[n],o={},r={} 110 | ;for(let e=1;e<=t.length;e++)r[e+i]=s[e],o[e+i]=!0,i+=p(t[e-1]) 111 | ;e[n]=r,e[n]._emit=o,e[n]._multi=!0}function Z(e){(e=>{ 112 | e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, 113 | delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ 114 | _wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope 115 | }),(e=>{if(Array.isArray(e.begin)){ 116 | if(e.skip||e.excludeBegin||e.returnBegin)throw W("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), 117 | K 118 | ;if("object"!=typeof e.beginScope||null===e.beginScope)throw W("beginScope must be object"), 119 | K;F(e,e.begin,{key:"beginScope"}),e.begin=m(e.begin,{joinWith:""})}})(e),(e=>{ 120 | if(Array.isArray(e.end)){ 121 | if(e.skip||e.excludeEnd||e.returnEnd)throw W("skip, excludeEnd, returnEnd not compatible with endScope: {}"), 122 | K 123 | ;if("object"!=typeof e.endScope||null===e.endScope)throw W("endScope must be object"), 124 | K;F(e,e.end,{key:"endScope"}),e.end=m(e.end,{joinWith:""})}})(e)}function V(e){ 125 | function t(t,n){ 126 | return RegExp(l(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":"")) 127 | }class n{constructor(){ 128 | this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} 129 | addRule(e,t){ 130 | t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), 131 | this.matchAt+=p(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) 132 | ;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(m(e,{joinWith:"|" 133 | }),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex 134 | ;const t=this.matcherRe.exec(e);if(!t)return null 135 | ;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] 136 | ;return t.splice(0,n),Object.assign(t,i)}}class s{constructor(){ 137 | this.rules=[],this.multiRegexes=[], 138 | this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ 139 | if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n 140 | ;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), 141 | t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ 142 | return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ 143 | this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ 144 | const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex 145 | ;let n=t.exec(e) 146 | ;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ 147 | const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} 148 | return n&&(this.regexIndex+=n.position+1, 149 | this.regexIndex===this.count&&this.considerAll()),n}} 150 | if(e.compilerExtensions||(e.compilerExtensions=[]), 151 | e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") 152 | ;return e.classNameAliases=i(e.classNameAliases||{}),function n(o,r){const a=o 153 | ;if(o.isCompiled)return a 154 | ;[I,B,Z,D].forEach((e=>e(o,r))),e.compilerExtensions.forEach((e=>e(o,r))), 155 | o.__beforeBegin=null,[T,L,P].forEach((e=>e(o,r))),o.isCompiled=!0;let c=null 156 | ;return"object"==typeof o.keywords&&o.keywords.$pattern&&(o.keywords=Object.assign({},o.keywords), 157 | c=o.keywords.$pattern, 158 | delete o.keywords.$pattern),c=c||/\w+/,o.keywords&&(o.keywords=$(o.keywords,e.case_insensitive)), 159 | a.keywordPatternRe=t(c,!0), 160 | r&&(o.begin||(o.begin=/\B|\b/),a.beginRe=t(a.begin),o.end||o.endsWithParent||(o.end=/\B|\b/), 161 | o.end&&(a.endRe=t(a.end)), 162 | a.terminatorEnd=l(a.end)||"",o.endsWithParent&&r.terminatorEnd&&(a.terminatorEnd+=(o.end?"|":"")+r.terminatorEnd)), 163 | o.illegal&&(a.illegalRe=t(o.illegal)), 164 | o.contains||(o.contains=[]),o.contains=[].concat(...o.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>i(e,{ 165 | variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?i(e,{ 166 | starts:e.starts?i(e.starts):null 167 | }):Object.isFrozen(e)?i(e):e))("self"===e?o:e)))),o.contains.forEach((e=>{n(e,a) 168 | })),o.starts&&n(o.starts,r),a.matcher=(e=>{const t=new s 169 | ;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" 170 | }))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" 171 | }),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){ 172 | return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{ 173 | constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}} 174 | const Y=n,Q=i,ee=Symbol("nomatch"),te=n=>{ 175 | const i=Object.create(null),s=Object.create(null),o=[];let r=!0 176 | ;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ 177 | disableAutodetect:!0,name:"Plain text",contains:[]};let p={ 178 | ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, 179 | languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", 180 | cssSelector:"pre code",languages:null,__emitter:c};function b(e){ 181 | return p.noHighlightRe.test(e)}function m(e,t,n){let i="",s="" 182 | ;"object"==typeof t?(i=e, 183 | n=t.ignoreIllegals,s=t.language):(G("10.7.0","highlight(lang, code, ...args) has been deprecated."), 184 | G("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), 185 | s=e,i=t),void 0===n&&(n=!0);const o={code:i,language:s};N("before:highlight",o) 186 | ;const r=o.result?o.result:E(o.language,o.code,n) 187 | ;return r.code=o.code,N("after:highlight",r),r}function E(e,n,s,o){ 188 | const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(R) 189 | ;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(R),n="" 190 | ;for(;t;){n+=R.substring(e,t.index) 191 | ;const s=_.case_insensitive?t[0].toLowerCase():t[0],o=(i=s,N.keywords[i]);if(o){ 192 | const[e,i]=o 193 | ;if(M.addText(n),n="",c[s]=(c[s]||0)+1,c[s]<=7&&(j+=i),e.startsWith("_"))n+=t[0];else{ 194 | const n=_.classNameAliases[e]||e;u(t[0],n)}}else n+=t[0] 195 | ;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(R)}var i 196 | ;n+=R.substring(e),M.addText(n)}function g(){null!=N.subLanguage?(()=>{ 197 | if(""===R)return;let e=null;if("string"==typeof N.subLanguage){ 198 | if(!i[N.subLanguage])return void M.addText(R) 199 | ;e=E(N.subLanguage,R,!0,S[N.subLanguage]),S[N.subLanguage]=e._top 200 | }else e=x(R,N.subLanguage.length?N.subLanguage:null) 201 | ;N.relevance>0&&(j+=e.relevance),M.__addSublanguage(e._emitter,e.language) 202 | })():l(),R=""}function u(e,t){ 203 | ""!==e&&(M.startScope(t),M.addText(e),M.endScope())}function d(e,t){let n=1 204 | ;const i=t.length-1;for(;n<=i;){if(!e._emit[n]){n++;continue} 205 | const i=_.classNameAliases[e[n]]||e[n],s=t[n];i?u(s,i):(R=s,l(),R=""),n++}} 206 | function h(e,t){ 207 | return e.scope&&"string"==typeof e.scope&&M.openNode(_.classNameAliases[e.scope]||e.scope), 208 | e.beginScope&&(e.beginScope._wrap?(u(R,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), 209 | R=""):e.beginScope._multi&&(d(e.beginScope,t),R="")),N=Object.create(e,{parent:{ 210 | value:N}}),N}function f(e,n,i){let s=((e,t)=>{const n=e&&e.exec(t) 211 | ;return n&&0===n.index})(e.endRe,i);if(s){if(e["on:end"]){const i=new t(e) 212 | ;e["on:end"](n,i),i.isMatchIgnored&&(s=!1)}if(s){ 213 | for(;e.endsParent&&e.parent;)e=e.parent;return e}} 214 | if(e.endsWithParent)return f(e.parent,n,i)}function b(e){ 215 | return 0===N.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function m(e){ 216 | const t=e[0],i=n.substring(e.index),s=f(N,e,i);if(!s)return ee;const o=N 217 | ;N.endScope&&N.endScope._wrap?(g(), 218 | u(t,N.endScope._wrap)):N.endScope&&N.endScope._multi?(g(), 219 | d(N.endScope,e)):o.skip?R+=t:(o.returnEnd||o.excludeEnd||(R+=t), 220 | g(),o.excludeEnd&&(R=t));do{ 221 | N.scope&&M.closeNode(),N.skip||N.subLanguage||(j+=N.relevance),N=N.parent 222 | }while(N!==s.parent);return s.starts&&h(s.starts,e),o.returnEnd?0:t.length} 223 | let w={};function y(i,o){const a=o&&o[0];if(R+=i,null==a)return g(),0 224 | ;if("begin"===w.type&&"end"===o.type&&w.index===o.index&&""===a){ 225 | if(R+=n.slice(o.index,o.index+1),!r){const t=Error(`0 width match regex (${e})`) 226 | ;throw t.languageName=e,t.badRule=w.rule,t}return 1} 227 | if(w=o,"begin"===o.type)return(e=>{ 228 | const n=e[0],i=e.rule,s=new t(i),o=[i.__beforeBegin,i["on:begin"]] 229 | ;for(const t of o)if(t&&(t(e,s),s.isMatchIgnored))return b(n) 230 | ;return i.skip?R+=n:(i.excludeBegin&&(R+=n), 231 | g(),i.returnBegin||i.excludeBegin||(R=n)),h(i,e),i.returnBegin?0:n.length})(o) 232 | ;if("illegal"===o.type&&!s){ 233 | const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"")+'"') 234 | ;throw e.mode=N,e}if("end"===o.type){const e=m(o);if(e!==ee)return e} 235 | if("illegal"===o.type&&""===a)return 1 236 | ;if(I>1e5&&I>3*o.index)throw Error("potential infinite loop, way more iterations than matches") 237 | ;return R+=a,a.length}const _=O(e) 238 | ;if(!_)throw W(a.replace("{}",e)),Error('Unknown language: "'+e+'"') 239 | ;const v=V(_);let k="",N=o||v;const S={},M=new p.__emitter(p);(()=>{const e=[] 240 | ;for(let t=N;t!==_;t=t.parent)t.scope&&e.unshift(t.scope) 241 | ;e.forEach((e=>M.openNode(e)))})();let R="",j=0,A=0,I=0,T=!1;try{ 242 | if(_.__emitTokens)_.__emitTokens(n,M);else{for(N.matcher.considerAll();;){ 243 | I++,T?T=!1:N.matcher.considerAll(),N.matcher.lastIndex=A 244 | ;const e=N.matcher.exec(n);if(!e)break;const t=y(n.substring(A,e.index),e) 245 | ;A=e.index+t}y(n.substring(A))}return M.finalize(),k=M.toHTML(),{language:e, 246 | value:k,relevance:j,illegal:!1,_emitter:M,_top:N}}catch(t){ 247 | if(t.message&&t.message.includes("Illegal"))return{language:e,value:Y(n), 248 | illegal:!0,relevance:0,_illegalBy:{message:t.message,index:A, 249 | context:n.slice(A-100,A+100),mode:t.mode,resultSoFar:k},_emitter:M};if(r)return{ 250 | language:e,value:Y(n),illegal:!1,relevance:0,errorRaised:t,_emitter:M,_top:N} 251 | ;throw t}}function x(e,t){t=t||p.languages||Object.keys(i);const n=(e=>{ 252 | const t={value:Y(e),illegal:!1,relevance:0,_top:l,_emitter:new p.__emitter(p)} 253 | ;return t._emitter.addText(e),t})(e),s=t.filter(O).filter(k).map((t=>E(t,e,!1))) 254 | ;s.unshift(n);const o=s.sort(((e,t)=>{ 255 | if(e.relevance!==t.relevance)return t.relevance-e.relevance 256 | ;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1 257 | ;if(O(t.language).supersetOf===e.language)return-1}return 0})),[r,a]=o,c=r 258 | ;return c.secondBest=a,c}function w(e){let t=null;const n=(e=>{ 259 | let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" 260 | ;const n=p.languageDetectRe.exec(t);if(n){const t=O(n[1]) 261 | ;return t||(X(a.replace("{}",n[1])), 262 | X("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} 263 | return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return 264 | ;if(N("before:highlightElement",{el:e,language:n 265 | }),e.dataset.highlighted)return void console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e) 266 | ;if(e.children.length>0&&(p.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), 267 | console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), 268 | console.warn("The element with unescaped HTML:"), 269 | console.warn(e)),p.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML) 270 | ;t=e;const i=t.textContent,o=n?m(i,{language:n,ignoreIllegals:!0}):x(i) 271 | ;e.innerHTML=o.value,e.dataset.highlighted="yes",((e,t,n)=>{const i=t&&s[t]||n 272 | ;e.classList.add("hljs"),e.classList.add("language-"+i) 273 | })(e,n,o.language),e.result={language:o.language,re:o.relevance, 274 | relevance:o.relevance},o.secondBest&&(e.secondBest={ 275 | language:o.secondBest.language,relevance:o.secondBest.relevance 276 | }),N("after:highlightElement",{el:e,result:o,text:i})}let y=!1;function _(){ 277 | "loading"!==document.readyState?document.querySelectorAll(p.cssSelector).forEach(w):y=!0 278 | }function O(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]} 279 | function v(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ 280 | s[e.toLowerCase()]=t}))}function k(e){const t=O(e) 281 | ;return t&&!t.disableAutodetect}function N(e,t){const n=e;o.forEach((e=>{ 282 | e[n]&&e[n](t)}))} 283 | "undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ 284 | y&&_()}),!1),Object.assign(n,{highlight:m,highlightAuto:x,highlightAll:_, 285 | highlightElement:w, 286 | highlightBlock:e=>(G("10.7.0","highlightBlock will be removed entirely in v12.0"), 287 | G("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{p=Q(p,e)}, 288 | initHighlighting:()=>{ 289 | _(),G("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, 290 | initHighlightingOnLoad:()=>{ 291 | _(),G("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") 292 | },registerLanguage:(e,t)=>{let s=null;try{s=t(n)}catch(t){ 293 | if(W("Language definition for '{}' could not be registered.".replace("{}",e)), 294 | !r)throw t;W(t),s=l} 295 | s.name||(s.name=e),i[e]=s,s.rawDefinition=t.bind(null,n),s.aliases&&v(s.aliases,{ 296 | languageName:e})},unregisterLanguage:e=>{delete i[e] 297 | ;for(const t of Object.keys(s))s[t]===e&&delete s[t]}, 298 | listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:v, 299 | autoDetection:k,inherit:Q,addPlugin:e=>{(e=>{ 300 | e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ 301 | e["before:highlightBlock"](Object.assign({block:t.el},t)) 302 | }),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ 303 | e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),o.push(e)}, 304 | removePlugin:e=>{const t=o.indexOf(e);-1!==t&&o.splice(t,1)}}),n.debugMode=()=>{ 305 | r=!1},n.safeMode=()=>{r=!0},n.versionString="11.9.0",n.regex={concat:h, 306 | lookahead:g,either:f,optional:d,anyNumberOfTimes:u} 307 | ;for(const t in j)"object"==typeof j[t]&&e(j[t]);return Object.assign(n,j),n 308 | },ne=te({});return ne.newInstance=()=>te({}),ne}() 309 | ;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `python` grammar compiled for Highlight.js 11.9.0 */ 310 | (()=>{var e=(()=>{"use strict";return e=>{ 311 | const n=e.regex,a=/[\p{XID_Start}_]\p{XID_Continue}*/u,s=["and","as","assert","async","await","break","case","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","match","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],i={ 312 | $pattern:/[A-Za-z]\w+|__\w+__/,keyword:s, 313 | built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"], 314 | literal:["__debug__","Ellipsis","False","None","NotImplemented","True"], 315 | type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"] 316 | },t={className:"meta",begin:/^(>>>|\.\.\.) /},r={className:"subst",begin:/\{/, 317 | end:/\}/,keywords:i,illegal:/#/},l={begin:/\{\{/,relevance:0},b={ 318 | className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{ 319 | begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/, 320 | contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ 321 | begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/, 322 | contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ 323 | begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/, 324 | contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/, 325 | end:/"""/,contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([uU]|[rR])'/,end:/'/, 326 | relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{ 327 | begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/, 328 | end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/, 329 | contains:[e.BACKSLASH_ESCAPE,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/, 330 | contains:[e.BACKSLASH_ESCAPE,l,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] 331 | },o="[0-9](_?[0-9])*",c=`(\\b(${o}))?\\.(${o})|\\b(${o})\\.`,d="\\b|"+s.join("|"),g={ 332 | className:"number",relevance:0,variants:[{ 333 | begin:`(\\b(${o})|(${c}))[eE][+-]?(${o})[jJ]?(?=${d})`},{begin:`(${c})[jJ]?`},{ 334 | begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${d})`},{ 335 | begin:`\\b0[bB](_?[01])+[lL]?(?=${d})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${d})` 336 | },{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${d})`},{begin:`\\b(${o})[jJ](?=${d})` 337 | }]},p={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:i, 338 | contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},m={ 339 | className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/, 340 | end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:i, 341 | contains:["self",t,g,b,e.HASH_COMMENT_MODE]}]};return r.contains=[b,g,t],{ 342 | name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:i, 343 | illegal:/(<\/|\?)|=>/,contains:[t,g,{begin:/\bself\b/},{beginKeywords:"if", 344 | relevance:0},{match:/\bor\b/,scope:"keyword"},b,p,e.HASH_COMMENT_MODE,{ 345 | match:[/\bdef/,/\s+/,a],scope:{1:"keyword",3:"title.function"},contains:[m]},{ 346 | variants:[{match:[/\bclass/,/\s+/,a,/\s*/,/\(\s*/,a,/\s*\)/]},{ 347 | match:[/\bclass/,/\s+/,a]}],scope:{1:"keyword",3:"title.class", 348 | 6:"title.class.inherited"}},{className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/, 349 | contains:[g,m,b]}]}}})();hljs.registerLanguage("python",e)})(); -------------------------------------------------------------------------------- /docs/license.md: -------------------------------------------------------------------------------- 1 |

License

2 | --- 3 | 4 |

5 | MIT License for PyShark 6 |

7 | 8 |

9 | Copyright (c) 2014 Dor Green 10 |

11 | 12 |

13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 |

20 | 21 |

22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 |

25 | 26 |

27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | SOFTWARE. 34 |

35 | 36 | -------------------------------------------------------------------------------- /docs/packet_layers.md: -------------------------------------------------------------------------------- 1 |

Packet Layers

2 | --- 3 | 4 | ### OSI model overview 5 | 6 |

7 | 8 | The Open Systems Interconnection (OSI) model is a conceptual model created by the International Organization for Standardization which enables communication systems to communicate using standard protocols. 9 |
10 |
11 | The OSI Model can be seen as a universal language for computer networking, which allows network traffic to be transferred and displayed between systems. 12 |
13 |
14 | This conceptual model is broken down into seven abstract layers, each one stacked upon the last. 15 |

16 | 17 | #### OSI model layers 18 | 19 |
    20 |
  • Application (Layer 7) - Displays the graphical User Interface (UI) - what the end-user sees
  • 21 | 22 |
  • Presentation (Layer 6) - Formats data to achieve effective communication between networked applications
  • 23 | 24 |
  • Session Layer (Layer 5) - Ensures connections between end-points are continuous and uninterrupted
  • 25 | 26 |
  • Transports Layer (Layer 4) - Ensures error-free data transfer between each endpoint by processing TCP and UDP protocols. At this layer, Pyshark can be used to analyze TCP traffic between two IP addresses
  • 27 | 28 |
  • Network Layer (Layer 3) - Ensures routing data for routers residing on this network are error-free
  • 29 | 30 |
  • Data Link Layer (Layer 2) - Identifies physical servers through two sub-layers, Media Access Control (MAC), and Logical Link Control (LLC)
  • 31 | 32 |
  • Physical Layer (Layer 1) - Comprised of all the physical hardware that processes network activity
  • 33 |
34 | 35 | 36 | #### OSI model layer protocol standards 37 | 38 |
    39 |
  • Application (Layer 7) - FTP, HTTP, POP3, SMTP, SNMP
  • 40 | 41 |
  • Presentation (Layer 6) - ASCH, MPEG, SSL, TLS
  • 42 | 43 |
  • Session Layer (Layer 5) - NetBIOS, SAP
  • 44 | 45 |
  • Transports Layer (Layer 4) - TCP, UDP
  • 46 | 47 |
  • Network Layer (Layer 3) - ARP, ICMP, IPSEC, IPV5, IPV6, MPLS
  • 48 | 49 |
  • Data Link Layer (Layer 2) - ATM, Fiber Cable, Frame Relay, PPP, RAPA
  • 50 | 51 |
  • Physical Layer (Layer 1) - ISDN, RS232, 100BaseTX
  • 52 |
53 | 54 | 55 | ### PyShark packet layer 56 | 57 |

58 | 59 | All packets processed with PyShark have layers, but these layers vary based on the packet type. These layers can be queried and the data elements within these layers can be extracted. Layer types can be accessed using the following parameter: 60 | 61 |

62 | 63 | ```python 64 | import pyshark 65 | 66 | capture = pyshark.LiveCapture(interface='your capture interface') 67 | for packet in capture: 68 | layers = packet.layers 69 | print(layers) 70 | ``` 71 | 72 | 73 | #### Common Layers: 74 | 75 |
    76 |
  • ETH Layer - Ethernet
  • 77 |
  • IP Layer - Internet Protocol
  • 78 |
  • TCP Layer - Transmission Control Protocol
  • 79 |
  • UDP Layer - User Datagram Protocol
  • 80 |
  • ARP Layer - Address Resolution Protocol
  • 81 |
82 | 83 | 84 | #### Other Layers: 85 | 86 |
    87 |
  • BROWSER Layer - Web browser
  • 88 |
  • DATA Layer - Normal data payload of a protocol
  • 89 |
  • DB-LSP-DISC Layer - Dropbox LAN Sync Discovery
  • 90 |
  • DHCP Layer - Dynamic Host Configuration Protocol
  • 91 |
  • HTTP Layer - Hypertext Transfer Protocol
  • 92 |
  • LLMNR Layer - Link-Local Multicast Name Resolution
  • 93 |
  • MAILSLOT Layer - Mailslot protocol is part of the SMB protocol family
  • 94 |
  • MSNMS Layer - Microsoft Network Messenger Service
  • 95 |
  • NAT-PMP Layer - NAT Port Mapping Protocol
  • 96 |
  • NBDGM Layer - NetBIOS Datagram Service
  • 97 |
  • NBNS Layer - NetBIOS Name Service
  • 98 |
  • SNMP Layer - Simple Network Management Protocol
  • 99 |
  • SSDP Layer - Simple Service Discovery Protocol
  • 100 |
  • TLS Layer - Transport Layer Security
  • 101 |
  • XML Layer - Extensible Markup Language
  • 102 |
103 | -------------------------------------------------------------------------------- /docs/parameters/file_capture_parameters.md: -------------------------------------------------------------------------------- 1 |

FileCapture Parameters

2 | --- 3 | 4 |

5 | 6 | The FileCapture module within PyShark has several parameters that are configurable. 7 |

8 | 9 | 10 | ```python 11 | 12 | import pyshark 13 | 14 | capture = pyshark.FileCapture(input_file=None, 15 | keep_packets=True, 16 | display_filter=None, 17 | only_summaries=False, 18 | decryption_key=None, 19 | encryption_type="wpa-pwk", 20 | decode_as=None, 21 | disable_protocol=None, 22 | tshark_path=None, 23 | override_prefs=None, 24 | use_json=False, 25 | use_ek=False, 26 | output_file=None, 27 | include_raw=False, 28 | eventloop=None, 29 | custom_parameters=None, 30 | debug=False) 31 | for packet in capture: 32 | # do something with the packet 33 | 34 | ``` 35 | 36 | 37 |
    38 | 39 |
  • input_file: 40 |
      41 |
    • type: string
    • 42 |
    • default: None
    • 43 |
    • description: File path of the capture (PCAP, PCAPNG)
    • 44 |
    45 |
  • 46 | 47 |
  • keep_packets: 48 |
      49 |
    • type: boolean
    • 50 |
    • default: True
    • 51 |
    • description: Whether to keep packets after reading them via next(). Used to conserve memory when reading 52 | large caps (can only be used along with the "lazy" option!)
    • 53 |
    54 |
  • 55 | 56 | 57 |
  • display_filter: 58 |
      59 |
    • type: string
    • 60 |
    • default: None
    • 61 |
    • description: Display (wireshark) filter to use.
    • 62 |
    63 |
  • 64 | 65 |
  • only_summaries: 66 |
      67 |
    • type: boolean
    • 68 |
    • default: False
    • 69 |
    • description: Only produce packet summaries, much faster but includes very little information.
    • 70 |
    71 |
  • 72 | 73 |
  • decryption_key: 74 |
      75 |
    • type: string
    • 76 |
    • default: None
    • 77 |
    • description: Optional key used to encrypt and decrypt captured traffic.
    • 78 |
    79 |
  • 80 | 81 |
  • encryption_type: 82 |
      83 |
    • type: string
    • 84 |
    • default: wpa-pwk
    • 85 |
    • description: Standard of encryption used in captured traffic (must be either 'WEP', 'WPA-PWD', or 86 | 'WPA-PWK'.
    • 87 |
    88 |
  • 89 | 90 |
  • decode_as: 91 |
      92 |
    • type: dictionary
    • 93 |
    • default: None
    • 94 |
    • description: A dictionary of {decode_criterion_string: decode_as_protocol} that are used to tell TShark 95 | to decode protocols in situations it wouldn't usually, for instance {'tcp.port==8888': 'http'} would make 96 | it attempt to decode any port 8888 traffic as HTTP. See TShark documentation for details.
    • 97 |
    98 |
  • 99 | 100 | 101 |
  • disable_protocol: 102 |
      103 |
    • type: string
    • 104 |
    • default: None
    • 105 |
    • description: Tells tshark to remove a dissector for a specific protocol.
    • 106 |
    107 |
  • 108 | 109 | 110 |
  • tshark_path: 111 |
      112 |
    • type: string
    • 113 |
    • default: None
    • 114 |
    • description: Path of the tshark binary.
    • 115 |
    116 |
  • 117 | 118 |
  • override_prefs: 119 |
      120 |
    • type: dictionary
    • 121 |
    • default: None
    • 122 |
    • description: A dictionary of TShark preferences to override, {PREFERENCE_NAME: PREFERENCE_VALUE, ...}
    • 123 |
    124 |
  • 125 | 126 | 127 |
  • use_json: 128 |
      129 |
    • type: boolean
    • 130 |
    • default: False
    • 131 |
    • description: DEPRECATED. Use use_ek instead.
    • 132 |
    133 |
  • 134 | 135 |
  • use_ek: 136 |
      137 |
    • type: boolean
    • 138 |
    • default: False
    • 139 |
    • description: Uses TShark in EK JSON mode. It is faster than XML but has slightly less data
    • 140 |
    141 |
  • 142 | 143 |
  • output_file: 144 |
      145 |
    • type: string
    • 146 |
    • default: None
    • 147 |
    • description: Save live captured packets to this file.
    • 148 |
    149 |
  • 150 | 151 |
  • include_raw: 152 |
      153 |
    • type: boolean
    • 154 |
    • default: False
    • 155 |
    • description: Whether to include raw packet data.
    • 156 |
    157 |
  • 158 | 159 |
  • eventloop: 160 |
      161 |
    • type: event loop object
    • 162 |
    • default: None
    • 163 |
    • description: Event loop to use for asynchronous operations.
    • 164 |
    165 |
  • 166 | 167 |
  • custom_parameters: 168 |
      169 |
    • type: dictionary
    • 170 |
    • default: None
    • 171 |
    • description: A dict of custom parameters to pass to TShark, i.e. {"--param": "value"} or 172 | else a list of parameters in the format ["--foo", "bar", "--baz", "foo"]
    • 173 |
    174 |
  • 175 | 176 |
  • debug: 177 |
      178 |
    • type: boolean
    • 179 |
    • default: False
    • 180 |
    • description: Whether to enable debug mode.
    • 181 |
    182 |
  • 183 | 184 |
-------------------------------------------------------------------------------- /docs/parameters/inmem_capture_parameters.md: -------------------------------------------------------------------------------- 1 |

InMemCapture Parameters

2 | --- 3 | 4 |

5 | 6 | The InMemCapture module within PyShark has several parameters that are configurable. 7 |

8 | 9 | 10 | ```python 11 | 12 | import pyshark 13 | 14 | capture = pyshark.InMemCapture(bpf_filter=None, 15 | display_filter=None, 16 | only_summaries=False, 17 | decryption_key=None, 18 | encryption_type='wpa-pwk', 19 | decode_as=None, 20 | disable_protocol=None, 21 | tshark_path=None, 22 | override_prefs=None, 23 | use_json=False, 24 | use_ek=False, 25 | linktype=LinkTypes.ETHERNET, 26 | include_raw=False, 27 | eventloop=None, 28 | custom_parameters=None, 29 | debug=False) 30 | for packet in capture: 31 | # do something with the packet 32 | 33 | ``` 34 | 35 |
    36 | 37 | 38 |
  • bpf_filter: 39 |
      40 |
    • type: string
    • 41 |
    • default: None
    • 42 |
    • description: BPF filter to use on packets.
    • 43 |
    44 |
  • 45 | 46 |
  • display_filter: 47 |
      48 |
    • type: string
    • 49 |
    • default: None
    • 50 |
    • description: Display (wireshark) filter to use.
    • 51 |
    52 |
  • 53 | 54 |
  • only_summaries: 55 |
      56 |
    • type: boolean
    • 57 |
    • default: False
    • 58 |
    • description: Only produce packet summaries, much faster but includes very little information.
    • 59 |
    60 |
  • 61 | 62 |
  • decryption_key: 63 |
      64 |
    • type: string
    • 65 |
    • default: None
    • 66 |
    • description: Optional key used to encrypt and decrypt captured traffic.
    • 67 |
    68 |
  • 69 | 70 |
  • encryption_type: 71 |
      72 |
    • type: string
    • 73 |
    • default: wpa-pwk
    • 74 |
    • description: Standard of encryption used in captured traffic (must be either 'WEP', 'WPA-PWD', or 'WPA-PWK'. Defaults to WPA-PWK.
    • 75 |
    76 |
  • 77 | 78 |
  • decode_as: 79 |
      80 |
    • type: dictionary
    • 81 |
    • default: None
    • 82 |
    • description: A dictionary of {decode_criterion_string: decode_as_protocol} that are used to tell TShark 83 | to decode protocols in situations it wouldn't usually, for instance {'tcp.port==8888': 'http'} would make 84 | it attempt to decode any port 8888 traffic as HTTP. See TShark documentation for details.
    • 85 |
    86 |
  • 87 | 88 |
  • disable_protocol: 89 |
      90 |
    • type: string
    • 91 |
    • default: None
    • 92 |
    • description: Tells TShark to remove a dissector for a specific protocol.
    • 93 |
    94 |
  • 95 | 96 |
  • tshark_path: 97 |
      98 |
    • type: string
    • 99 |
    • default: None
    • 100 |
    • description: Path of the TShark binary.
    • 101 |
    102 |
  • 103 | 104 |
  • override_prefs: 105 |
      106 |
    • type: dictionary
    • 107 |
    • default: None
    • 108 |
    • description: A dictionary of TShark preferences to override, {PREFERENCE_NAME: PREFERENCE_VALUE, ...}
    • 109 |
    110 |
  • 111 | 112 |
  • use_json: 113 |
      114 |
    • type: boolean
    • 115 |
    • default: False
    • 116 |
    • description: DEPRECATED. Use use_ek instead.
    • 117 |
    118 |
  • 119 | 120 |
  • use_ek: 121 |
      122 |
    • type: boolean
    • 123 |
    • default: False
    • 124 |
    • description: Uses TShark in EK JSON mode. It is faster than XML but has slightly less data.
    • 125 |
    126 |
  • 127 | 128 |
  • linktype: 129 |
      130 |
    • type: class variable
    • 131 |
    • default: LinkTypes.ETHERNET
    • 132 |
    • linktype variables:
    • 133 |
        134 |
      • LinkTypes.NULL
      • 135 |
      • LinkTypes.ETHERNET
      • 136 |
      • LinkTypes.IEEE802_5
      • 137 |
      • LinkTypes.PPP
      • 138 |
      • LinkTypes.IEEE802_11
      • 139 |
      140 |
    • description: Defines different link types with their corresponding numeric values.
    • 141 | 142 |
    143 |
  • 144 | 145 |
  • include_raw: 146 |
      147 |
    • type: boolean
    • 148 |
    • default: False
    • 149 |
    • description: Whether to include raw packet data.
    • 150 |
    151 |
  • 152 | 153 |
  • eventloop: 154 |
      155 |
    • type: event loop object
    • 156 |
    • default: None
    • 157 |
    • description: Event loop to use for asynchronous operations.
    • 158 |
    159 |
  • 160 | 161 |
  • custom_parameters: 162 |
      163 |
    • type: dictionary
    • 164 |
    • default: None
    • 165 |
    • description: A dict of custom parameters to pass to TShark, i.e. {"--param": "value"} or 166 | else a list of parameters in the format ["--foo", "bar", "--baz", "foo"]
    • 167 |
    168 |
  • 169 | 170 |
  • debug: 171 |
      172 |
    • type: boolean
    • 173 |
    • default: False
    • 174 |
    • description: Whether to enable debug mode.
    • 175 |
    176 |
  • 177 | 178 |
179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /docs/parameters/live_capture_parameters.md: -------------------------------------------------------------------------------- 1 |

LiveCapture Parameters

2 | --- 3 | 4 |

5 | 6 | The LiveCapture module within PyShark has several parameters that are configurable. 7 |

8 | 9 | 10 | ```python 11 | 12 | import pyshark 13 | 14 | capture = pyshark.LiveCapture(interface=None, 15 | bpf_filter=None, 16 | display_filter=None, 17 | only_summaries=False, 18 | decryption_key=None, 19 | encryption_type='wpa-pwk', 20 | output_file=None, 21 | decode_as=None, 22 | disable_protocol=None, 23 | tshark_path=None, 24 | override_prefs=None, 25 | capture_filter=None, 26 | monitor_mode=False, 27 | use_json=False, 28 | use_ek=False, 29 | include_raw=False, 30 | eventloop=None, 31 | custom_parameters=None, 32 | debug=False) 33 | for packet in capture: 34 | # do something with the packet 35 | 36 | ``` 37 | 38 | 39 |
    40 | 41 |
  • interface: 42 |
      43 |
    • type: string
    • 44 |
    • default: None
    • 45 |
    • description: Name of the interface to sniff on or a list of names (str). If not given, runs on all interfaces.
    • 46 |
    47 |
  • 48 | 49 |
  • bpf_filter: 50 |
      51 |
    • type: string
    • 52 |
    • default: None
    • 53 |
    • description: BPF filter to use on packets.
    • 54 |
    55 |
  • 56 | 57 |
  • display_filter: 58 |
      59 |
    • type: string
    • 60 |
    • default: None
    • 61 |
    • description: Display (wireshark) filter to use.
    • 62 |
    63 |
  • 64 | 65 |
  • only_summaries: 66 |
      67 |
    • type: boolean
    • 68 |
    • default: False
    • 69 |
    • description: Only produce packet summaries, much faster but includes very little information.
    • 70 |
    71 |
  • 72 | 73 |
  • decryption_key: 74 |
      75 |
    • type: string
    • 76 |
    • default: None
    • 77 |
    • description: Optional key used to encrypt and decrypt captured traffic.
    • 78 |
    79 |
  • 80 | 81 |
  • encryption_type: 82 |
      83 |
    • type: string
    • 84 |
    • default: wpa-pwk
    • 85 |
    • description: Standard of encryption used in captured traffic (must be either 'WEP', 'WPA-PWD', or 86 | 'WPA-PWK'.
    • 87 |
    88 |
  • 89 | 90 |
  • output_file: 91 |
      92 |
    • type: string
    • 93 |
    • default: None
    • 94 |
    • description: Save live captured packets to this file.
    • 95 |
    96 |
  • 97 | 98 |
  • decode_as: 99 |
      100 |
    • type: dictionary
    • 101 |
    • default: None
    • 102 |
    • description: A dictionary of {decode_criterion_string: decode_as_protocol} that are used to tell TShark 103 | to decode protocols in situations it wouldn't usually, for instance {'tcp.port==8888': 'http'} would make 104 | it attempt to decode any port 8888 traffic as HTTP. See TShark documentation for details.
    • 105 |
    106 |
  • 107 | 108 |
  • tshark_path: 109 |
      110 |
    • type: string
    • 111 |
    • default: None
    • 112 |
    • description: Path of the TShark binary.
    • 113 |
    114 |
  • 115 | 116 |
  • override_prefs: 117 |
      118 |
    • type: dictionary
    • 119 |
    • default: None
    • 120 |
    • description: A dictionary of TShark preferences to override, {PREFERENCE_NAME: PREFERENCE_VALUE, ...}
    • 121 |
    122 |
  • 123 | 124 |
  • capture_filter: 125 |
      126 |
    • type: string
    • 127 |
    • default: None
    • 128 |
    • description: Capture (wireshark) filter to use.
    • 129 |
    130 |
  • 131 | 132 |
  • monitor_mode: 133 |
      134 |
    • type: boolean
    • 135 |
    • default: False
    • 136 |
    • description: Whether to enable monitor mode on the interface.
    • 137 |
    138 |
  • 139 | 140 |
  • disable_protocol: 141 |
      142 |
    • type: string
    • 143 |
    • default: None
    • 144 |
    • description: Tells TShark to remove a dissector for a specific protocol.
    • 145 |
    146 |
  • 147 | 148 |
  • use_json: 149 |
      150 |
    • type: boolean
    • 151 |
    • default: False
    • 152 |
    • description: DEPRECATED. Use use_ek instead.
    • 153 |
    154 |
  • 155 | 156 |
  • use_ek: 157 |
      158 |
    • type: boolean
    • 159 |
    • default: False
    • 160 |
    • description: Uses TShark in EK JSON mode. It is faster than XML but has slightly less data.
    • 161 |
    162 |
  • 163 | 164 | 165 |
  • include_raw: 166 |
      167 |
    • type: boolean
    • 168 |
    • default: False
    • 169 |
    • description: Whether to include raw packet data.
    • 170 |
    171 |
  • 172 | 173 |
  • eventloop: 174 |
      175 |
    • type: event loop object
    • 176 |
    • default: None
    • 177 |
    • description: Event loop to use for asynchronous operations.
    • 178 |
    179 |
  • 180 | 181 |
  • custom_parameters: 182 |
      183 |
    • type: dictionary
    • 184 |
    • default: None
    • 185 |
    • description: A dict of custom parameters to pass to TShark, i.e. {"--param": "value"} or 186 | else a list of parameters in the format ["--foo", "bar", "--baz", "foo"]
    • 187 |
    188 |
  • 189 | 190 |
  • debug: 191 |
      192 |
    • type: boolean
    • 193 |
    • default: False
    • 194 |
    • description: Whether to enable debug mode.
    • 195 |
    196 |
  • 197 | 198 |
199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /docs/parameters/livering_capture_parameters.md: -------------------------------------------------------------------------------- 1 |

LiveRingCapture Parameters

2 | --- 3 | 4 |

5 | 6 | The LiveRingCapture module within PyShark has several parameters that are configurable. 7 |

8 | 9 | 10 | ```python 11 | 12 | import pyshark 13 | 14 | capture = pyshark.LiveRingCapture(ring_file_size=1024, 15 | num_ring_files=1, 16 | ring_file_name='/tmp/pyshark.pcap', 17 | interface=None, 18 | bpf_filter=None, 19 | display_filter=None, 20 | only_summaries=False, 21 | decryption_key=None, 22 | encryption_type='wpa-pwk', 23 | decode_as=None, 24 | disable_protocol=None, 25 | tshark_path=None, 26 | override_prefs=None, 27 | capture_filter=None, 28 | use_json=False, 29 | use_ek=False, 30 | include_raw=False, 31 | eventloop=None, 32 | custom_parameters=None, 33 | debug=False) 34 | for packet in capture: 35 | # do something with the packet 36 | 37 | ``` 38 | 39 | 40 |
    41 | 42 |
  • ring_file_size: 43 |
      44 |
    • type: int
    • 45 |
    • default: 1024
    • 46 |
    • description: Size of the ring file in kB.
    • 47 |
    48 |
  • 49 | 50 |
  • num_ring_files: 51 |
      52 |
    • type: int
    • 53 |
    • default: 1
    • 54 |
    • description: Number of ring files to keep.
    • 55 |
    56 |
  • 57 | 58 |
  • ring_file_name: 59 |
      60 |
    • type: string
    • 61 |
    • default: /tmp/pyshark.pcap
    • 62 |
    • description: Name of the ring file.
    • 63 |
    64 |
  • 65 | 66 | 67 |
  • interface: 68 |
      69 |
    • type: string
    • 70 |
    • default: None
    • 71 |
    • description: Name of the interface to sniff on or a list of names (str). If not given, runs on all interfaces.
    • 72 |
    73 |
  • 74 | 75 |
  • bpf_filter: 76 |
      77 |
    • type: string
    • 78 |
    • default: None
    • 79 |
    • description: BPF filter to use on packets.
    • 80 |
    81 |
  • 82 | 83 |
  • display_filter: 84 |
      85 |
    • type: string
    • 86 |
    • default: None
    • 87 |
    • description: Display (wireshark) filter to use.
    • 88 |
    89 |
  • 90 | 91 |
  • only_summaries: 92 |
      93 |
    • type: boolean
    • 94 |
    • default: False
    • 95 |
    • description: Only produce packet summaries, much faster but includes very little information.
    • 96 |
    97 |
  • 98 | 99 |
  • decryption_key: 100 |
      101 |
    • type: string
    • 102 |
    • default: None
    • 103 |
    • description: Optional key used to encrypt and decrypt captured traffic.
    • 104 |
    105 |
  • 106 | 107 |
  • encryption_type: 108 |
      109 |
    • type: string
    • 110 |
    • default: wpa-pwk
    • 111 |
    • description: Standard of encryption used in captured traffic (must be either 'WEP', 'WPA-PWD', or 112 | 'WPA-PWK'.
    • 113 |
    114 |
  • 115 | 116 |
  • decode_as: 117 |
      118 |
    • type: dictionary
    • 119 |
    • default: None
    • 120 |
    • description: A dictionary of {decode_criterion_string: decode_as_protocol} that are used to tell TShark 121 | to decode protocols in situations it wouldn't usually, for instance {'tcp.port==8888': 'http'} would make 122 | it attempt to decode any port 8888 traffic as HTTP. See TShark documentation for details.
    • 123 |
    124 |
  • 125 | 126 |
  • tshark_path: 127 |
      128 |
    • type: string
    • 129 |
    • default: None
    • 130 |
    • description: Path of the TShark binary.
    • 131 |
    132 |
  • 133 | 134 |
  • override_prefs: 135 |
      136 |
    • type: dictionary
    • 137 |
    • default: None
    • 138 |
    • description: A dictionary of TShark preferences to override, {PREFERENCE_NAME: PREFERENCE_VALUE, ...}
    • 139 |
    140 |
  • 141 | 142 |
  • capture_filter: 143 |
      144 |
    • type: string
    • 145 |
    • default: None
    • 146 |
    • description: Capture (wireshark) filter to use.
    • 147 |
    148 |
  • 149 | 150 |
  • disable_protocol: 151 |
      152 |
    • type: string
    • 153 |
    • default: None
    • 154 |
    • description: Tells TShark to remove a dissector for a specific protocol.
    • 155 |
    156 |
  • 157 | 158 |
  • use_ek: 159 |
      160 |
    • type: boolean
    • 161 |
    • default: False
    • 162 |
    • description: Uses TShark in EK JSON mode. It is faster than XML but has slightly less data.
    • 163 |
    164 |
  • 165 | 166 |
  • use_json: 167 |
      168 |
    • type: boolean
    • 169 |
    • default: False
    • 170 |
    • description: DEPRECATED. Use use_ek instead.
    • 171 |
    172 |
  • 173 | 174 |
  • include_raw: 175 |
      176 |
    • type: boolean
    • 177 |
    • default: False
    • 178 |
    • description: Whether to include raw packet data.
    • 179 |
    180 |
  • 181 | 182 |
  • eventloop: 183 |
      184 |
    • type: event loop object
    • 185 |
    • default: None
    • 186 |
    • description: Event loop to use for asynchronous operations.
    • 187 |
    188 |
  • 189 | 190 | 191 |
  • custom_parameters: 192 |
      193 |
    • type: dictionary
    • 194 |
    • default: None
    • 195 |
    • description: A dict of custom parameters to pass to TShark, i.e. {"--param": "value"} or 196 | else a list of parameters in the format ["--foo", "bar", "--baz", "foo"]
    • 197 |
    198 |
  • 199 | 200 |
  • debug: 201 |
      202 |
    • type: boolean
    • 203 |
    • default: False
    • 204 |
    • description: Whether to enable debug mode.
    • 205 |
    206 |
  • 207 | 208 |
209 | -------------------------------------------------------------------------------- /docs/parameters/pipe_capture_parameters.md: -------------------------------------------------------------------------------- 1 |

PipeCapture Parameters

2 | --- 3 | 4 |

5 | 6 | The PipeCapture module within PyShark has several parameters that are configurable. 7 |

8 | 9 | 10 | ```python 11 | 12 | import pyshark 13 | 14 | capture = pyshark.InMemCapture(pipe=None, 15 | display_filter=None, 16 | only_summaries=False, 17 | decryption_key=None, 18 | encryption_type='wpa-pwk', 19 | decode_as=None, 20 | disable_protocol=None, 21 | tshark_path=None, 22 | override_prefs=None, 23 | use_json=False, 24 | use_ek=False, 25 | include_raw=False, 26 | eventloop=None, 27 | custom_parameters=None, 28 | debug=False) 29 | for packet in capture: 30 | # do something with the packet 31 | 32 | ``` 33 | 34 |
    35 | 36 |
  • pipe: 37 |
      38 |
    • type:
    • 39 |
    • description: A section of shared memory that acts as a virtual file, temporarily holding data and passing it in a single direction from one process to another.
    • 40 |
    41 |
  • 42 | 43 | 44 |
  • display_filter: 45 |
      46 |
    • type: string
    • 47 |
    • default: None
    • 48 |
    • description: Display (wireshark) filter to use.
    • 49 |
    50 |
  • 51 | 52 |
  • only_summaries: 53 |
      54 |
    • type: boolean
    • 55 |
    • default: False
    • 56 |
    • description: Only produce packet summaries, much faster but includes very little information.
    • 57 |
    58 |
  • 59 | 60 |
  • decryption_key: 61 |
      62 |
    • type: string
    • 63 |
    • default: None
    • 64 |
    • description: Optional key used to encrypt and decrypt captured traffic.
    • 65 |
    66 |
  • 67 | 68 |
  • encryption_type: 69 |
      70 |
    • type: string
    • 71 |
    • default: wpa-pwk
    • 72 |
    • description: Standard of encryption used in captured traffic (must be either 'WEP', 'WPA-PWD', or 'WPA-PWK'.
    • 73 |
    74 |
  • 75 | 76 |
  • decode_as: 77 |
      78 |
    • type: dictionary
    • 79 |
    • default: None
    • 80 |
    • description: A dictionary of {decode_criterion_string: decode_as_protocol} that are used to tell TShark 81 | to decode protocols in situations it wouldn't usually, for instance {'tcp.port==8888': 'http'} would make 82 | it attempt to decode any port 8888 traffic as HTTP. See TShark documentation for details.
    • 83 |
    84 |
  • 85 | 86 |
  • disable_protocol: 87 |
      88 |
    • type: string
    • 89 |
    • default: None
    • 90 |
    • description: Tells TShark to remove a dissector for a specific protocol.
    • 91 |
    92 |
  • 93 | 94 |
  • tshark_path: 95 |
      96 |
    • type: string
    • 97 |
    • default: None
    • 98 |
    • description: Path of the TShark binary.
    • 99 |
    100 |
  • 101 | 102 |
  • override_prefs: 103 |
      104 |
    • type: dictionary
    • 105 |
    • default: None
    • 106 |
    • description: A dictionary of TShark preferences to override, {PREFERENCE_NAME: PREFERENCE_VALUE, ...}
    • 107 |
    108 |
  • 109 | 110 |
  • use_json: 111 |
      112 |
    • type: boolean
    • 113 |
    • default: False
    • 114 |
    • description: DEPRECATED. Use use_ek instead.
    • 115 |
    116 |
  • 117 | 118 |
  • use_ek: 119 |
      120 |
    • type: boolean
    • 121 |
    • default: False
    • 122 |
    • description: Uses TShark in EK JSON mode. It is faster than XML but has slightly less data.
    • 123 |
    124 |
  • 125 | 126 |
  • include_raw: 127 |
      128 |
    • type: boolean
    • 129 |
    • default: False
    • 130 |
    • description: Whether to include raw packet data.
    • 131 |
    132 |
  • 133 | 134 |
  • eventloop: 135 |
      136 |
    • type: event loop object
    • 137 |
    • default: None
    • 138 |
    • description: Event loop to use for asynchronous operations.
    • 139 |
    140 |
  • 141 | 142 |
  • custom_parameters: 143 |
      144 |
    • type: dictionary
    • 145 |
    • default: None
    • 146 |
    • description: A dict of custom parameters to pass to TShark, i.e. {"--param": "value"} or 147 | else a list of parameters in the format ["--foo", "bar", "--baz", "foo"]
    • 148 |
    149 |
  • 150 | 151 |
  • debug: 152 |
      153 |
    • type: boolean
    • 154 |
    • default: False
    • 155 |
    • description: Whether to enable debug mode.
    • 156 |
    157 |
  • 158 | 159 |
160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /docs/parameters/remote_capture_parameters.md: -------------------------------------------------------------------------------- 1 |

RemoteCapture Parameters

2 | --- 3 | 4 |

5 | 6 | The RemoteCapture module within PyShark has several parameters that are configurable. 7 |

8 | 9 | 10 | ```python 11 | 12 | import pyshark 13 | 14 | capture = pyshark.RemoteCapture(remote_host=None, 15 | remote_interface=None, 16 | remote_port=2002, 17 | bpf_filter=None, 18 | only_summaries=False, 19 | decryption_key=None, 20 | encryption_type="wpa-pwk", 21 | decode_as=None, 22 | disable_protocol=None, 23 | tshark_path=None, 24 | override_prefs=None, 25 | eventloop=None, 26 | debug=False,) 27 | for packet in capture: 28 | # do something with the packet 29 | 30 | ``` 31 | 32 | 33 |
    34 | 35 |
  • remote_host: 36 |
      37 |
    • type: string
    • 38 |
    • default: required argument
    • 39 |
    • description: The remote host to capture on (IP or hostname). Should be running rpcapd.
    • 40 |
    41 |
  • 42 | 43 |
  • remote_interface: 44 |
      45 |
    • type: string
    • 46 |
    • default: required argument
    • 47 |
    • description: The remote interface on the remote machine to capture on.
    • 48 |
    49 |
  • 50 | 51 |
  • remote_port: 52 |
      53 |
    • type: int
    • 54 |
    • default: 2002
    • 55 |
    • description: The remote port the rpcapd (remote daemon) service is listening on.
    • 56 |
    57 |
  • 58 | 59 |
  • bpf_filter: 60 |
      61 |
    • type: string
    • 62 |
    • default: None
    • 63 |
    • description: BPF filter to use on packets.
    • 64 |
    65 |
  • 66 | 67 |
  • only_summaries: 68 |
      69 |
    • type: boolean
    • 70 |
    • default: False
    • 71 |
    • description: Only produce packet summaries, much faster but includes very little information.
    • 72 |
    73 |
  • 74 | 75 |
  • decryption_key: 76 |
      77 |
    • type: string
    • 78 |
    • default: None
    • 79 |
    • description: Optional key used to encrypt and decrypt captured traffic.
    • 80 |
    81 |
  • 82 | 83 |
  • encryption_type: 84 |
      85 |
    • type: string
    • 86 |
    • default: wpa-pwk
    • 87 |
    • description: Standard of encryption used in captured traffic (must be either 'WEP', 'WPA-PWD', or 'WPA-PWK'.
    • 88 |
    89 |
  • 90 | 91 |
  • decode_as: 92 |
      93 |
    • type: dictionary
    • 94 |
    • default: None
    • 95 |
    • description: A dictionary of {decode_criterion_string: decode_as_protocol} that are used to tell TShark 96 | to decode protocols in situations it wouldn't usually, for instance {'tcp.port==8888': 'http'} would make 97 | it attempt to decode any port 8888 traffic as HTTP. See TShark documentation for details.
    • 98 |
    99 |
  • 100 | 101 |
  • tshark_path: 102 |
      103 |
    • type: string
    • 104 |
    • default: None
    • 105 |
    • description: ath of the TShark binary.
    • 106 |
    107 |
  • 108 | 109 |
  • override_prefs: 110 |
      111 |
    • type: dictionary
    • 112 |
    • default: None
    • 113 |
    • description: A dictionary of TShark preferences to override, {PREFERENCE_NAME: PREFERENCE_VALUE, ...}
    • 114 |
    115 |
  • 116 | 117 |
  • disable_protocol: 118 |
      119 |
    • type: string
    • 120 |
    • default: None
    • 121 |
    • description: Tells TShark to remove a dissector for a specific protocol.
    • 122 |
    123 |
  • 124 | 125 |
  • debug: 126 |
      127 |
    • type: boolean
    • 128 |
    • default: False
    • 129 |
    • description: Whether to enable debug mode.
    • 130 |
    131 |
  • 132 | 133 |
134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /docs/parsing/eth_packets.md: -------------------------------------------------------------------------------- 1 |

Parsing Ethernet Packets

2 | 3 | --- 4 | 5 | 6 |

7 | 8 | PyShark has a lot of flexibility to parse various types of information from an individual network packet. Below are some of the items that can be parsed from the Ethernet layer of a packet. 9 | 10 |

11 | 12 | #### Ethernet filtering with display_filter 13 | 14 | 15 | ```python 16 | import pyshark 17 | 18 | capture = pyshark.LiveCapture(interface='your capture interface', display_filter='eth') 19 | for packet in capture: 20 | try: 21 | # obtain all the field names within the ETH packets 22 | field_names = packet.eth._all_fields 23 | 24 | # obtain all the field values 25 | field_values = packet.eth._all_fields.values() 26 | 27 | # enumerate the field names and field values 28 | for field_name, field_value in zip(field_names, field_values): 29 | print(f'{field_name}: {field_value}') 30 | except AttributeError as error: 31 | 32 | ``` 33 | 34 | Output: 35 | 36 | ```plaintext 37 | eth.dst: 01:00:5e:00:00:fb 38 | eth.dst_resolved: 01:00:5e:00:00:fb 39 | eth.dst.oui: 65630 40 | eth.dst.oui_resolved: ICANN, IANA Department 41 | eth.addr: 01:00:5e:00:00:fb 42 | eth.addr_resolved: 01:00:5e:00:00:fb 43 | eth.addr.oui: 65630 44 | eth.addr.oui_resolved: ICANN, IANA Department 45 | eth.dst.lg: False 46 | eth.lg: False 47 | eth.dst.ig: True 48 | eth.ig: True 49 | eth.src: 00:18:dd:54:00:a2 50 | eth.src_resolved: 00:18:dd:54:00:a2 51 | eth.src.oui: 6365 52 | eth.src.oui_resolved: Silicondust Engineering Ltd 53 | eth.src.lg: False 54 | eth.src.ig: False 55 | eth.type: 0x0800 56 | 57 | ``` -------------------------------------------------------------------------------- /docs/parsing/ip_packets.md: -------------------------------------------------------------------------------- 1 |

Parsing IP Packets

2 | 3 | --- 4 | 5 | 6 |

7 | 8 | PyShark has a lot of flexibility to parse various types of information from an individual network packet. Below are some of the items that can be parsed from the IP layer. 9 | 10 |

11 | 12 | #### IP Address filtering with display_filter 13 | 14 | 15 | ```python 16 | import pyshark 17 | 18 | capture = pyshark.LiveCapture(interface='your capture interface', display_filter='ip') 19 | for packet in capture: 20 | try: 21 | # obtain all the field names within the IP packets 22 | field_names = packet.ip._all_fields 23 | 24 | # obtain all the field values 25 | field_values = packet.ip._all_fields.values() 26 | 27 | # enumerate the field names and field values 28 | for field_name, field_value in zip(field_names, field_values): 29 | print(f'{field_name}: {field_value}') 30 | except AttributeError as error: 31 | 32 | ``` 33 | 34 | Output: 35 | 36 | ```plaintext 37 | ip.version: 4 38 | ip.hdr_len: 20 39 | ip.dsfield: 0x00 40 | ip.dsfield.dscp: 0 41 | ip.dsfield.ecn: 0 42 | ip.len: 88 43 | ip.id: 0x1cf3 44 | ip.flags: 0x02 45 | ip.flags.rb: False 46 | ip.flags.df: True 47 | ip.flags.mf: False 48 | ip.frag_offset: 0 49 | ip.ttl: 1 50 | _ws.expert: Expert Info (Note/Sequence): "Time To Live" != 255 for a packet sent to the Local Network Control Block (see RFC 3171) 51 | ip.ttl.lncb: "Time To Live" != 255 for a packet sent to the Local Network Control Block (see RFC 3171) 52 | _ws.expert.message: "Time To Live" != 255 for a packet sent to the Local Network Control Block (see RFC 3171) 53 | _ws.expert.severity: 4194304 54 | _ws.expert.group: 33554432 55 | ip.proto: 17 56 | ip.checksum: 0x649b 57 | ip.checksum.status: 2 58 | ip.src: 192.168.86.99 59 | ip.addr: 192.168.86.99 60 | ip.src_host: 192.168.86.99 61 | ip.host: 192.168.86.99 62 | ip.dst: 224.0.0.251 63 | ip.dst_host: 224.0.0.251 64 | 65 | ``` 66 | 67 | 68 | #### Source and destination IP Address filtering 69 | 70 |

71 | 72 | This example shows how to access packet elements, such the source and destination IP addresses. 73 | 74 |

75 | 76 | 77 | ```python 78 | import pyshark 79 | 80 | capture = pyshark.LiveCapture(interface='your capture interface') 81 | for packet in capture: 82 | protocol = packet.transport_layer 83 | source_address = packet.ip.src 84 | source_port = packet[packet.transport_layer].srcport 85 | destination_address = packet.ip.dst 86 | destination_port = packet[packet.transport_layer].dstport 87 | packet_time = packet.sniff_time 88 | packet_timestamp = packet.sniff_timestamp 89 | ``` 90 | 91 | Output: 92 | 93 | ```paintext 94 | Protocol type: TCP 95 | Source address: 192.168.86.139 96 | Source port: 63187 97 | Destination address: 192.168.86.56 98 | Destination port: 32206 99 | Date and Time: 2023-01-25 10:55:18.625206 100 | Timestamp: 1674662118.625206000 101 | ``` 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /docs/parsing/tcp_packets.md: -------------------------------------------------------------------------------- 1 |

Parsing TCP Packets

2 | 3 | --- 4 | 5 |

6 | 7 | PyShark has a lot of flexibility to parse various types of information from an individual network packet. Below are some of the ways that Transmission Control Protocol (TCP) items can be parsed. 8 | 9 |

10 | 11 | #### Filtering TCP Packets by source and destination 12 | 13 |

14 | 15 | This example shows how to filter TCP packets by source and destination IP addresses. 16 | 17 |

18 | 19 | 20 | ```python 21 | import pyshark 22 | 23 | capture = pyshark.LiveCapture(interface='your capture interface', display_filter='tcp') 24 | for packet in capture: 25 | protocol = packet.transport_layer 26 | source_address = packet.ip.src 27 | source_port = packet[packet.transport_layer].srcport 28 | destination_address = packet.ip.dst 29 | destination_port = packet[packet.transport_layer].dstport 30 | packet_time = packet.sniff_time 31 | packet_timestamp = packet.sniff_timestamp 32 | ``` 33 | 34 | Output: 35 | 36 | ``` 37 | Protocol type: TCP 38 | Source address: 3.161.193.27 39 | Source port: 443 40 | Destination address: 192.168.86.22 41 | Destination port: 58805 42 | Date and Time: 2024-06-12 10:15:00.533168 43 | Timestamp: 1718201700.533168000 44 | ``` 45 | 46 | 47 | #### Filtering HTTPS Packets 48 | 49 |

50 | 51 | This example shows how to access the field elements within the TCP Layer. It also show how to filter the packets for TCP Port 443, which is used 52 | by the Hypertext Transfer Protocol Secure (HTTPS) protocol that is used for secures communication. 53 | 54 |

55 | 56 | ```python 57 | import pyshark 58 | 59 | capture = pyshark.LiveCapture(interface='your capture interface') 60 | for packet in capture: 61 | if hasattr(packet, 'tcp') and packet[packet.transport_layer].dstport == '443': 62 | print(packet) 63 | 64 | ``` 65 | 66 | Output: 67 | 68 | ```plaintext 69 | Layer ETH: 70 | Destination: 28:bd:89:cf:9d:21 71 | Address: 28:bd:89:cf:9d:21 72 | .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) 73 | .... ...0 .... .... .... .... = IG bit: Individual address (unicast) 74 | Source: f8:ff:c2:50:40:95 75 | .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) 76 | .... ...0 .... .... .... .... = IG bit: Individual address (unicast) 77 | Type: IPv4 (0x0800) 78 | Address: f8:ff:c2:50:40:95 79 | Layer IP: 80 | 0100 .... = Version: 4 81 | .... 0101 = Header Length: 20 bytes (5) 82 | Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) 83 | 0000 00.. = Differentiated Services Codepoint: Default (0) 84 | .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0) 85 | Total Length: 82 86 | Identification: 0x0000 (0) 87 | 010. .... = Flags: 0x2, Don't fragment 88 | 0... .... = Reserved bit: Not set 89 | .1.. .... = Don't fragment: Set 90 | ..0. .... = More fragments: Not set 91 | ...0 0000 0000 0000 = Fragment Offset: 0 92 | Time to Live: 64 93 | Protocol: TCP (6) 94 | Header Checksum: 0x2507 [validation disabled] 95 | Header checksum status: Unverified 96 | Source Address: 192.168.86.139 97 | Destination Address: 140.82.114.25 98 | Layer TCP: 99 | Source Port: 53871 100 | Destination Port: 443 101 | Stream index: 9 102 | Conversation completeness: Incomplete (12) 103 | TCP Segment Len: 30 104 | Sequence Number: 2 (relative sequence number) 105 | Sequence Number (raw): 2977936731 106 | Next Sequence Number: 32 (relative sequence number) 107 | Acknowledgment Number: 27 (relative ack number) 108 | Acknowledgment number (raw): 1788271858 109 | 1000 .... = Header Length: 32 bytes (8) 110 | Flags: 0x018 (PSH, ACK) 111 | 000. .... .... = Reserved: Not set 112 | ...0 .... .... = Accurate ECN: Not set 113 | .... 0... .... = Congestion Window Reduced: Not set 114 | .... .0.. .... = ECN-Echo: Not set 115 | .... ..0. .... = Urgent: Not set 116 | .... ...1 .... = Acknowledgment: Set 117 | .... .... 1... = Push: Set 118 | .... .... .0.. = Reset: Not set 119 | .... .... ..0. = Syn: Not set 120 | .... .... ...0 = Fin: Not set 121 | TCP Flags: ·······AP··· 122 | Window: 2048 123 | Calculated window size: 2048 124 | Window size scaling factor: -1 (unknown) 125 | Checksum: 0x1528 [unverified] 126 | Checksum Status: Unverified 127 | Urgent Pointer: 0 128 | Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps 129 | TCP Option - No-Operation (NOP) 130 | Kind: No-Operation (1) 131 | TCP Option - Timestamps 132 | Length: 10 133 | Timestamp value: 1749519908: TSval 1749519908, TSecr 1741751960 134 | Timestamp echo reply: 1741751960 135 | Timestamps 136 | Time since first frame in this TCP stream: 14.819388000 seconds 137 | Time since previous frame in this TCP stream: 0.000061000 seconds 138 | TCP payload (30 bytes) 139 | TCP Option - No-Operation (NOP) 140 | Kind: No-Operation (1) 141 | Kind: Time Stamp Option (8) 142 | Layer TLS: 143 | TLSv1.2 Record Layer: Application Data Protocol: Hypertext Transfer Protocol 144 | Content Type: Application Data (23) 145 | Version: TLS 1.2 (0x0303) 146 | Length: 25 147 | Encrypted Application Data: d6c30b735ac2bb8038c9903b7c9205c8cf4cd4b13cbb8895bb 148 | Application Data Protocol: Hypertext Transfer Protocol 149 | 150 | ``` 151 | 152 | 153 | #### HTTPS Filtering with bpf_filter 154 | 155 |

156 | 157 | This example shows how to filter Hypertext Transfer Protocol Secure (HTTPS) protocol packets using the bpf_filter option. 158 | 159 |

160 | 161 | ```python 162 | import pyshark 163 | 164 | capture = pyshark.LiveCapture(interface='your capture interface', bpf_filter='tcp port 443') 165 | for packet in capture: 166 | print(packet) 167 | 168 | ``` 169 | 170 | Output: 171 | 172 | ```plaintext 173 | Packet (Length: 1514) 174 | Layer ETH 175 | : Destination: 28:bd:89:cf:9d:21 176 | Address: 28:bd:89:cf:9d:21 177 | .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) 178 | .... ...0 .... .... .... .... = IG bit: Individual address (unicast) 179 | Source: f8:ff:c2:50:40:95 180 | .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) 181 | .... ...0 .... .... .... .... = IG bit: Individual address (unicast) 182 | Type: IPv4 (0x0800) 183 | Address: f8:ff:c2:50:40:95 184 | Layer IP 185 | : 0100 .... = Version: 4 186 | .... 0101 = Header Length: 20 bytes (5) 187 | Differentiated Services Field: 0x02 (DSCP: CS0, ECN: ECT(0)) 188 | 0000 00.. = Differentiated Services Codepoint: Default (0) 189 | .... ..10 = Explicit Congestion Notification: ECN-Capable Transport codepoint '10' (2) 190 | Total Length: 1500 191 | Identification: 0x0000 (0) 192 | 010. .... = Flags: 0x2, Don't fragment 193 | 0... .... = Reserved bit: Not set 194 | .1.. .... = Don't fragment: Set 195 | ..0. .... = More fragments: Not set 196 | ...0 0000 0000 0000 = Fragment Offset: 0 197 | Time to Live: 64 198 | Protocol: TCP (6) 199 | Header Checksum: 0x2cc9 [validation disabled] 200 | Header checksum status: Unverified 201 | Source Address: 192.168.86.22 202 | Destination Address: 52.96.189.50 203 | Layer TCP 204 | : Source Port: 53995 205 | Destination Port: 443 206 | Stream index: 0 207 | Conversation completeness: Incomplete (0) 208 | ..0. .... = RST: Absent 209 | ...0 .... = FIN: Absent 210 | .... 0... = Data: Absent 211 | .... .0.. = ACK: Absent 212 | .... ..0. = SYN-ACK: Absent 213 | .... ...0 = SYN: Absent 214 | Completeness Flags: [ Null ] 215 | TCP Segment Len: 1448 216 | Sequence Number: 1 (relative sequence number) 217 | Sequence Number (raw): 1499305713 218 | Next Sequence Number: 1449 (relative sequence number) 219 | Acknowledgment Number: 1 (relative ack number) 220 | Acknowledgment number (raw): 132473324 221 | 1000 .... = Header Length: 32 bytes (8) 222 | Flags: 0x010 (ACK) 223 | 000. .... .... = Reserved: Not set 224 | ...0 .... .... = Accurate ECN: Not set 225 | .... 0... .... = Congestion Window Reduced: Not set 226 | .... .0.. .... = ECN-Echo: Not set 227 | .... ..0. .... = Urgent: Not set 228 | .... ...1 .... = Acknowledgment: Set 229 | .... .... 0... = Push: Not set 230 | .... .... .0.. = Reset: Not set 231 | .... .... ..0. = Syn: Not set 232 | .... .... ...0 = Fin: Not set 233 | TCP Flags: ·······A···· 234 | Window: 1915 235 | Calculated window size: 1915 236 | Window size scaling factor: -1 (unknown) 237 | Checksum: 0x925a [unverified] 238 | Checksum Status: Unverified 239 | Urgent Pointer: 0 240 | Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps 241 | TCP Option - No-Operation (NOP) 242 | Kind: No-Operation (1) 243 | TCP Option - Timestamps: TSval 2735122551, TSecr 49907491 244 | Length: 10 245 | Timestamp value: 2735122551 246 | Timestamp echo reply: 49907491 247 | Timestamps 248 | Time since first frame in this TCP stream: 0.000000000 seconds 249 | Time since previous frame in this TCP stream: 0.000000000 seconds 250 | SEQ/ACK analysis 251 | Bytes in flight: 1448 252 | Bytes sent since last PSH flag: 1448 253 | TCP payload (1448 bytes) 254 | TCP segment data (1448 bytes) 255 | TCP Option - No-Operation (NOP) 256 | Kind: No-Operation (1) 257 | Kind: Time Stamp Option (8) 258 | Layer TLS 259 | : TLS segment data (1448 bytes) 260 | 261 | 262 | ``` 263 | 264 | #### HTTP Filtering with bpf_filter and display_filter 265 | 266 | 267 |

268 | 269 | This example shows how to filter Hypertext Transfer Protocol (HTTP) protocol packets using both the bpf_filter and display_filteroptions. 270 | 271 |

272 | 273 | 274 | ```python 275 | import pyshark 276 | 277 | capture = pyshark.LiveCapture(interface='your capture interface', bpf_filter='tcp', display_filter='http') 278 | for packet in capture: 279 | print(packet) 280 | 281 | ``` 282 | 283 | ```plaintext 284 | Layer HTTP 285 | : HTTP/1.1 200 OK\r\n 286 | Expert Info (Chat/Sequence): HTTP/1.1 200 OK\r\n 287 | HTTP/1.1 200 OK\r\n 288 | Severity level: Chat 289 | Group: Sequence 290 | Response Version: HTTP/1.1 291 | Status Code: 200 292 | Status Code Description: OK 293 | Response Phrase: OK 294 | Accept-Ranges: bytes\r\n 295 | Cache-Control: max-age=7200\r\n 296 | Content-Type: application/ocsp-response\r\n 297 | Date: Wed, 12 Jun 2024 18:37:29 GMT\r\n 298 | Last-Modified: Wed, 12 Jun 2024 18:17:16 GMT\r\n 299 | Server: ECAcc (agc/7F39)\r\n 300 | Content-Length: 471\r\n 301 | Content length: 471 302 | HTTP response 1/1 303 | Time since request: 0.023253000 seconds 304 | Request in frame: 24857 305 | Request URI: http://ocsp.digicert.com/ME8wTTBLMEkwRzAHBgUrDgMCGgQUOdKLcf4dGbZfs%2FEojyO8BFlcQ5UEFE4iVCAYlebjbuYP%2Bvq5Eu0GF485AhAE8i7MIfy0OCrCi48tZB%2FA 306 | File Data: 471 bytes 307 | \r\n 308 | Age: 1213\r\n 309 | X-Cache: HIT\r\n 310 | ``` 311 | 312 | 313 | #### HTTP Layer Filtering 314 | 315 |

316 | 317 | This example shows how to access the field elements within the HTTP layer. The code below queries a Packet Capture (PCAP) file for all the URLs within the HTTP layer with the field name request.full_uri. 318 | 319 |

320 | 321 | 322 | ```python 323 | import pyshark 324 | 325 | capture = pyshark.FileCapture(pcap_file) 326 | for packet in capture: 327 | if 'HTTP' in str(packet.layers): 328 | field_names = packet.http._all_fields 329 | field_values = packet.http._all_fields.values() 330 | for field_name in field_names: 331 | for field_value in field_values: 332 | if field_name == 'http.request.full_uri' and field_value.startswith('http'): 333 | print(f'{field_value}') 334 | 335 | ``` 336 | 337 | Output: 338 | 339 | ```plaintext 340 | http://eu.httpbin.org 341 | http://www.neverssl.com 342 | http://www.testingmcafeesites.com 343 | ``` 344 | 345 | ``` 346 | 347 | -------------------------------------------------------------------------------- /docs/parsing/udp_packets.md: -------------------------------------------------------------------------------- 1 |

Parsing UDP Packets

2 | 3 | --- 4 | 5 |

6 | 7 | PyShark has a lot of flexibility to parse various types of information from an individual network packet. Below are some of the ways that User Datagram Protocol (UDP) items can be parsed. 8 | 9 |

10 | 11 | 12 | #### DNS Filtering 13 | 14 |

15 | 16 | This example shows how to filter the packets for UDP Port 53, which is used by the Domain Name System (DNS) service. 17 | 18 |

19 | 20 | ```python 21 | import pyshark 22 | 23 | capture = pyshark.LiveCapture(interface='your capture interface') 24 | for packet in capture: 25 | try: 26 | if hasattr(packet, 'udp') and packet[packet.transport_layer].dstport == '53': 27 | if packet.dns.qry_name: 28 | source_address = packet.ip.src 29 | dns_location = packet.dns.qry_name 30 | print(f'DNS Request from IP: {source_address} to DNS Name: {dns_location}') 31 | elif packet.dns.resp_name: 32 | source_address = packet.ip.src 33 | dns_location = packet.dns.resp_name 34 | print(f'DNS Response from IP: {source_address} to DNS Name: {dns_location}') 35 | except AttributeError as error: 36 | pass 37 | 38 | ``` 39 | 40 | Output: 41 | 42 | ``` 43 | DNS Request from IP: 192.168.86.22 to DNS Name: www.google.com 44 | DNS Request from IP: 192.168.86.22 to DNS Name: weather-data.apple.com 45 | DNS Request from IP: 192.168.86.22 to DNS Name: stocks-data-service.apple.com 46 | DNS Request from IP: 192.168.86.22 to DNS Name: alive.github.com 47 | DNS Request from IP: 192.168.86.22 to DNS Name: www.cnn.com 48 | ``` 49 | 50 | 51 | #### DNS Filtering with display_filter 52 | 53 |

54 | 55 | This example shows how to filter Domain Name System (DNS) packets using the display_filter option. 56 | 57 |

58 | 59 | ```python 60 | import pyshark 61 | 62 | capture = pyshark.LiveCapture(interface='your capture interface', display_filter='dns') 63 | for packet in capture: 64 | try: 65 | # obtain all the field names within the DNS packets 66 | field_names = packet.dns._all_fields 67 | 68 | # obtain all the field values 69 | field_values = packet.dns._all_fields.values() 70 | 71 | # enumerate the field names and field values 72 | for field_name, field_value in zip(field_names, field_values): 73 | print(f'{field_name}: {field_value}') 74 | except AttributeError as error: 75 | pass 76 | 77 | ``` 78 | 79 | Output: 80 | 81 | ```paintext 82 | dns.id: 0x588b 83 | dns.flags: 0x8180 84 | dns.flags.response: True 85 | dns.flags.opcode: 0 86 | dns.flags.authoritative: False 87 | dns.flags.truncated: False 88 | dns.flags.recdesired: True 89 | dns.flags.recavail: True 90 | dns.flags.z: False 91 | dns.flags.authenticated: False 92 | dns.flags.checkdisable: False 93 | dns.flags.rcode: 0 94 | dns.count.queries: 1 95 | dns.count.answers: 4 96 | dns.count.auth_rr: 0 97 | dns.count.add_rr: 0 98 | : Queries 99 | dns.qry.name: cnn.com 100 | dns.qry.name.len: 7 101 | dns.count.labels: 2 102 | dns.qry.type: 1 103 | dns.qry.class: 0x0001 104 | dns.resp.name: cnn.com 105 | dns.resp.type: 1 106 | dns.resp.class: 0x0001 107 | dns.resp.ttl: 53 108 | dns.resp.len: 4 109 | dns.a: 151.101.3.5 110 | dns.response_to: 1729 111 | dns.time: 0.030207000 112 | ``` 113 | 114 | #### DNS Filtering with bpf_filter 115 | 116 |

117 | 118 | This example shows how to filter Domain Name System (DNS) packets using the bpf_filter option. 119 | 120 |

121 | 122 | ```python 123 | import pyshark 124 | 125 | capture = pyshark.LiveCapture(interface='your capture interface', bpf_filter='port 53') 126 | for packet in capture: 127 | try: 128 | # obtain all the field names within the DNS packets 129 | field_names = packet.dns._all_fields 130 | 131 | # obtain all the field values 132 | field_values = packet.dns._all_fields.values() 133 | 134 | # enumerate the field names and field values 135 | for field_name, field_value in zip(field_names, field_values): 136 | print(f'{field_name}: {field_value}') 137 | except AttributeError as error: 138 | pass 139 | 140 | ``` 141 | 142 | Output: 143 | 144 | ```paintext 145 | dns.id: 0xc9c1 146 | dns.flags: 0x8180 147 | dns.flags.response: True 148 | dns.flags.opcode: 0 149 | dns.flags.authoritative: False 150 | dns.flags.truncated: False 151 | dns.flags.recdesired: True 152 | dns.flags.recavail: True 153 | dns.flags.z: False 154 | dns.flags.authenticated: False 155 | dns.flags.checkdisable: False 156 | dns.flags.rcode: 0 157 | dns.count.queries: 1 158 | dns.count.answers: 4 159 | dns.count.auth_rr: 0 160 | dns.count.add_rr: 0 161 | : Queries 162 | dns.qry.name: cnn.com 163 | dns.qry.name.len: 7 164 | dns.count.labels: 2 165 | dns.qry.type: 1 166 | dns.qry.class: 0x0001 167 | dns.resp.name: cnn.com 168 | dns.resp.type: 1 169 | dns.resp.class: 0x0001 170 | dns.resp.ttl: 3 171 | dns.resp.len: 4 172 | dns.a: 151.101.195.5 173 | dns.response_to: 1 174 | dns.time: 0.067113000 175 | ``` 176 | 177 | #### DHCP Filtering with packet.layers 178 | 179 |

180 | 181 | This example shows how to filter DHCP (Dynamic Host Configuration Protocol) packets using packet.layers. 182 | 183 |

184 | 185 | ```python 186 | import pyshark 187 | 188 | capture = pyshark.LiveCapture(interface='your capture interface') 189 | for packet in capture: 190 | if 'DHCP' in str(packet.layers): 191 | try: 192 | # obtain all the field names within the DHCP packets 193 | field_names = packet.dhcp._all_fields 194 | 195 | # obtain all the field values 196 | field_values = packet.dhcp._all_fields.values() 197 | 198 | # enumerate the field names and field values 199 | for field_name, field_value in zip(field_names, field_values): 200 | print(f'{field_name}: {field_value}') 201 | except AttributeError as error: 202 | pass 203 | 204 | ``` 205 | 206 | Output: 207 | 208 | ```paintext 209 | dhcp.type: 1 210 | dhcp.hw.type: 0x01 211 | dhcp.hw.len: 6 212 | dhcp.hops: 0 213 | dhcp.id: 0x666719b8 214 | dhcp.secs: 1 215 | dhcp.flags: 0x8000 216 | dhcp.flags.bc: True 217 | dhcp.flags.reserved: 0x0000 218 | dhcp.ip.client: 0.0.0.0 219 | dhcp.ip.your: 0.0.0.0 220 | dhcp.ip.server: 0.0.0.0 221 | dhcp.ip.relay: 0.0.0.0 222 | dhcp.hw.mac_addr: 28:bd:89:cf:9d:21 223 | dhcp.hw.addr_padding: 00:00:00:00:00:00:00:00:00:00 224 | dhcp.server: gwifi_rouge_dhcp_detection 225 | dhcp.file: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 226 | dhcp.cookie: 99.130.83.99 227 | dhcp.option.type: 53 228 | dhcp.option.length: 1 229 | dhcp.option.value: 01 230 | dhcp.option.dhcp: 1 231 | dhcp.option.end: 255 232 | 233 | ``` 234 | 235 | #### DHCP Filtering with display_filter 236 | 237 |

238 | 239 | This example shows how to filter DHCP (Dynamic Host Configuration Protocol) packets using the display_filter option. 240 | 241 |

242 | 243 | ```python 244 | import pyshark 245 | 246 | capture = pyshark.LiveCapture(interface='your capture interface', display_filter='dhcp') 247 | for packet in capture: 248 | try: 249 | # obtain all the field names within the DHCP packets 250 | field_names = packet.dhcp._all_fields 251 | 252 | # obtain all the field values 253 | field_values = packet.dhcp._all_fields.values() 254 | 255 | # enumerate the field names and field values 256 | for field_name, field_value in zip(field_names, field_values): 257 | print(f'{field_name}: {field_value}') 258 | except AttributeError as error: 259 | pass 260 | 261 | ``` 262 | 263 | Output: 264 | 265 | ```paintext 266 | dhcp.type: 1 267 | dhcp.hw.type: 0x01 268 | dhcp.hw.len: 6 269 | dhcp.hops: 0 270 | dhcp.id: 0x66671c2e 271 | dhcp.secs: 1 272 | dhcp.flags: 0x8000 273 | dhcp.flags.bc: True 274 | dhcp.flags.reserved: 0x0000 275 | dhcp.ip.client: 0.0.0.0 276 | dhcp.ip.your: 0.0.0.0 277 | dhcp.ip.server: 0.0.0.0 278 | dhcp.ip.relay: 0.0.0.0 279 | dhcp.hw.mac_addr: 28:bd:89:cf:9d:21 280 | dhcp.hw.addr_padding: 00:00:00:00:00:00:00:00:00:00 281 | dhcp.server: gwifi_rouge_dhcp_detection 282 | dhcp.file: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 283 | dhcp.cookie: 99.130.83.99 284 | dhcp.option.type: 53 285 | dhcp.option.length: 1 286 | dhcp.option.value: 01 287 | dhcp.option.dhcp: 1 288 | dhcp.option.end: 255 289 | 290 | ``` 291 | 292 | #### DHCP Filtering with bpf_filter 293 | 294 |

295 | 296 | This example shows how to filter DHCP (Dynamic Host Configuration Protocol) packets using the bpf_filter option. 297 | 298 |

299 | 300 | ```python 301 | import pyshark 302 | 303 | capture = pyshark.LiveCapture(interface='your capture interface', bpf_filter='port 67 and port 68') 304 | for packet in capture: 305 | try: 306 | # obtain all the field names within the DHCP packets 307 | field_names = packet.dhcp._all_fields 308 | 309 | # obtain all the field values 310 | field_values = packet.dhcp._all_fields.values() 311 | 312 | # enumerate the field names and field values 313 | for field_name, field_value in zip(field_names, field_values): 314 | print(f'{field_name}: {field_value}') 315 | except AttributeError as error: 316 | pass 317 | 318 | ``` 319 | 320 | Output: 321 | 322 | ```paintext 323 | dhcp.type: 1 324 | dhcp.hw.type: 0x01 325 | dhcp.hw.len: 6 326 | dhcp.hops: 0 327 | dhcp.id: 0x66671c4c 328 | dhcp.secs: 1 329 | dhcp.flags: 0x8000 330 | dhcp.flags.bc: True 331 | dhcp.flags.reserved: 0x0000 332 | dhcp.ip.client: 0.0.0.0 333 | dhcp.ip.your: 0.0.0.0 334 | dhcp.ip.server: 0.0.0.0 335 | dhcp.ip.relay: 0.0.0.0 336 | dhcp.hw.mac_addr: 28:bd:89:cf:9d:21 337 | dhcp.hw.addr_padding: 00:00:00:00:00:00:00:00:00:00 338 | dhcp.server: gwifi_rouge_dhcp_detection 339 | dhcp.file: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 340 | dhcp.cookie: 99.130.83.99 341 | dhcp.option.type: 53 342 | dhcp.option.length: 1 343 | dhcp.option.value: 01 344 | dhcp.option.dhcp: 1 345 | dhcp.option.end: 255 346 | 347 | ``` 348 | 349 | #### NTP Filtering 350 | 351 |

352 | 353 | This example shows how to filter the packets for UDP Port 123, which is used by the Network Time Protocol protocol. 354 | 355 |

356 | 357 | ```python 358 | import pyshark 359 | 360 | capture = pyshark.LiveCapture(interface='your capture interface') 361 | for packet in capture: 362 | try: 363 | if hasattr(packet, 'udp') and packet[packet.transport_layer].dstport == '123': 364 | print(packet.layers) 365 | field_names = packet.ntp._all_fields 366 | field_values = packet.ntp._all_fields.values() 367 | for field_name, field_value in zip(field_names, field_values): 368 | print(f'Field Name: {field_name} -- Field Value: {field_value}') 369 | except AttributeError as error: 370 | pass 371 | 372 | ``` 373 | 374 | Output: 375 | 376 | ```paintext 377 | Field Name: ntp.flags -- Field Value: 0xe3 378 | Field Name: ntp.flags.li -- Field Value: 3 379 | Field Name: ntp.flags.vn -- Field Value: 4 380 | Field Name: ntp.flags.mode -- Field Value: 3 381 | Field Name: ntp.stratum -- Field Value: 0 382 | Field Name: ntp.ppoll -- Field Value: 8 383 | Field Name: ntp.precision -- Field Value: 0 384 | Field Name: ntp.rootdelay -- Field Value: 0 385 | Field Name: ntp.rootdispersion -- Field Value: 0 386 | Field Name: ntp.refid -- Field Value: 00:00:00:00 387 | Field Name: ntp.reftime -- Field Value: NULL 388 | Field Name: ntp.org -- Field Value: NULL 389 | Field Name: ntp.rec -- Field Value: NULL 390 | Field Name: ntp.xmt -- Field Value: Jan 29, 2023 23:43:52.523570988 UTC 391 | 392 | ``` 393 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs-material 2 | mkdocs-git-revision-date-localized-plugin -------------------------------------------------------------------------------- /examples/async_operations.py: -------------------------------------------------------------------------------- 1 | # This example shows how to use asyncio programming with PyShark. 2 | # In the example below PyShark is executed in LiveCapture mode. 3 | # During this operation another function is also called. 4 | # Asyncio allows these two operations to run in concurrent with each other. 5 | 6 | ################################################################################## 7 | # Python imports required for basic operations 8 | ################################################################################## 9 | # Standard library imports 10 | import asyncio 11 | import threading 12 | from typing import Any 13 | import queue 14 | # Third-party imports 15 | import pyshark 16 | # Import Packet class from pyshark.packet.packet 17 | from pyshark.packet.packet import Packet 18 | 19 | # Thread-safe queue to hold captured packets 20 | packet_queue: queue.Queue = queue.Queue() 21 | 22 | def capture_packets(interface: str) -> None: 23 | """ 24 | Captures packets on the specified network interface using pyshark.LiveCapture 25 | and puts each packet into the packet_queue. 26 | 27 | :param interface: The network interface to capture packets on. 28 | :param type interface: str 29 | """ 30 | capture = pyshark.LiveCapture(interface=interface) 31 | 32 | def packet_handler(packet: Any) -> None: 33 | packet_queue.put(packet) 34 | 35 | capture.apply_on_packets(packet_handler, timeout=100) 36 | 37 | async def process_packets() -> None: 38 | """ 39 | Asynchronously processes packets from the packet_queue. 40 | """ 41 | while True: 42 | try: 43 | packet = packet_queue.get_nowait() 44 | await process_packet(packet) 45 | except queue.Empty: 46 | await asyncio.sleep(0.1) 47 | 48 | async def process_packet(packet: Packet) -> None: 49 | """ 50 | Processes an individual packet, extracting and printing IP and TCP information. 51 | 52 | :param packet: The packet to process. 53 | :param type packet: pyshark.packet.packet.Packet 54 | """ 55 | try: 56 | if 'IP' in packet: 57 | print(f'IP Packet: {packet.ip.src} -> {packet.ip.dst}') 58 | if 'TCP' in packet: 59 | print(f'TCP Packet: {packet.tcp.srcport} -> {packet.tcp.dstport}') 60 | except AttributeError: 61 | # Handle packets that don't have the expected attributes 62 | pass 63 | 64 | async def do_other_tasks() -> None: 65 | """ 66 | Simulates performing other asynchronous tasks. 67 | """ 68 | while True: 69 | print("Performing other tasks...") 70 | await asyncio.sleep(2) # Simulate doing other work 71 | 72 | async def main() -> None: 73 | """ 74 | Main coroutine that starts the packet capture in a separate thread and 75 | runs the packet processing and other tasks concurrently. 76 | """ 77 | interface = 'en0' 78 | 79 | # Start the packet capture in a separate thread 80 | capture_thread = threading.Thread(target=capture_packets, args=(interface,)) 81 | capture_thread.start() 82 | 83 | await asyncio.gather( 84 | process_packets(), 85 | do_other_tasks() 86 | ) 87 | 88 | if __name__ == '__main__': 89 | try: 90 | asyncio.run(main()) 91 | except KeyboardInterrupt: 92 | print("Shutting down...") 93 | -------------------------------------------------------------------------------- /examples/dns_filtering_examples.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | ################################################################################## 4 | # “AS-IS” Clause 5 | # 6 | # Except as represented in this agreement, all work produced by Developer is 7 | # provided “AS IS”. Other than as provided in this agreement, Developer makes no 8 | # other warranties, express or implied, and hereby disclaims all implied warranties, 9 | # including any warranty of merchantability and warranty of fitness for a particular 10 | # purpose. 11 | ################################################################################## 12 | 13 | ################################################################################## 14 | # 15 | # Date Completed: February 15, 2020 16 | # Author: John Bumgarner 17 | # 18 | # Date Revised: June 15, 2024 19 | # Revised by: John Bumgarner 20 | # 21 | # This Python script is designed to process, filter and analyze .pcap files using 22 | # the Python module PyShark. 23 | ################################################################################## 24 | 25 | ############################################################################################# 26 | # The Python module PyShark is a wrapper for the Wireshark CLI (TShark). 27 | # 28 | # reference: https://kiminewt.github.io/pyshark 29 | # reference: https://www.wireshark.org 30 | # reference: https://www.wireshark.org/docs/man-pages/tshark.html 31 | ############################################################################################# 32 | 33 | ############################################################################################### 34 | # DNS Query Type 35 | # 36 | # The "Query Type" field in a DNS query specifies the type of DNS record that is being requested. 37 | # Each type has a specific numerical value associated with it. Here are some common DNS query types 38 | # and their corresponding numerical values: 39 | # 40 | # A (1): IPv4 address record. This type of query is used to get the IP address associated with a domain name. 41 | # AAAA (28): IPv6 address record. This type of query is used to get the IPv6 address associated with a domain name. 42 | # MX (15): Mail exchange record. This type of query is used to get the mail servers associated with a domain. 43 | # CNAME (5): Canonical name record. This type of query is used to alias one domain name to another. 44 | # NS (2): Name server record. This type of query is used to get the authoritative name servers for a domain. 45 | # PTR (12): Pointer record. This type of query is used for reverse DNS lookups, where an IP address is mapped to a domain name. 46 | # TXT (16): Text record. This type of query is used to retrieve arbitrary text data associated with a domain. 47 | # 48 | # DNS Query Class 49 | # 50 | # The "Query Class" field in a DNS query specifies the class of the query. 51 | # The most common class is "IN" (Internet), which is used for queries related to the Internet. 52 | # Here are some common DNS query classes and their corresponding numerical values: 53 | # 54 | # IN (1): Internet. This is the most commonly used class. 55 | # CH (3): Chaos. This class is used for querying Chaosnet. 56 | # HS (4): Hesiod. This class is used for querying Hesiod systems. 57 | 58 | import pyshark 59 | import logging 60 | 61 | # Configure logging 62 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 63 | 64 | def parse_dns_info(packet: pyshark.packet.packet.Packet) -> iter: 65 | """ 66 | Parses DNS information from the given packet. 67 | 68 | :param packet: A pyshark packet object. 69 | :type packet: pyshark.packet.packet.Packet 70 | 71 | :yields: Formatted DNS request or response information. 72 | :rtype: iter of str 73 | """ 74 | try: 75 | if hasattr(packet.dns, 'qry_name'): 76 | source_address = packet.ip.src 77 | dns_location = packet.dns.qry_name 78 | query_type = packet.dns.qry_type 79 | query_class = packet.dns.qry_class 80 | yield f'DNS Request from IP: {source_address}\nTo DNS Name: {dns_location}\nQuery Type: {query_type}\nQuery Class: {query_class}' 81 | except AttributeError: 82 | pass 83 | 84 | try: 85 | if hasattr(packet.dns, 'resp_name'): 86 | source_address = packet.ip.src 87 | dns_location = packet.dns.resp_name 88 | transaction_id = packet.dns.id 89 | response_code = packet.dns.flags_rcode 90 | answers = packet.dns.resp_addr 91 | yield f'DNS Response from IP: {source_address}\nTo DNS Name: {dns_location}\nTransaction ID: {transaction_id}\nResponse Code: {response_code}\nAnswers: {answers}' 92 | except AttributeError: 93 | pass 94 | 95 | 96 | def filter_dns(network_interface: str, filter_type: str = 'transport_layer') -> iter: 97 | """ 98 | Captures and filters DNS packets from the specified network interface. 99 | 100 | :param network_interface: The network interface to capture packets from. 101 | :type network_interface: str 102 | 103 | :param filter_type: The type of filter to apply ('transport_layer', 'bpf', or 'display'). 104 | :type filter_type: str 105 | 106 | :yields: Formatted DNS request or response information. 107 | :rtype: iter of str 108 | """ 109 | if filter_type == 'transport_layer': 110 | capture = pyshark.LiveCapture(interface=network_interface) 111 | elif filter_type == 'bpf': 112 | capture = pyshark.LiveCapture(interface=network_interface, bpf_filter='udp port 53') 113 | elif filter_type == 'display': 114 | capture = pyshark.LiveCapture(interface=network_interface, display_filter='dns') 115 | else: 116 | raise ValueError("Invalid filter_type. Choose 'transport_layer', 'bpf', or 'display'.") 117 | 118 | for packet in capture: 119 | if filter_type == 'transport_layer' and not (hasattr(packet, 'udp') and packet.udp.dstport == '53'): 120 | continue 121 | yield from parse_dns_info(packet) 122 | 123 | def main(): 124 | """ 125 | Main function to capture and print DNS packet information. 126 | """ 127 | network_interface = 'en0' # Change to the appropriate interface name 128 | filter_type = 'transport_layer' # Choose 'transport_layer', 'bpf', or 'display' 129 | 130 | try: 131 | for dns_info in filter_dns(network_interface, filter_type): 132 | if dns_info is not None: 133 | print(dns_info) 134 | except Exception as error: 135 | logging.error(f"An error occurred: {error}") 136 | 137 | if __name__ == "__main__": 138 | main() 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /examples/frame_filtering_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | ################################################################################## 4 | # “AS-IS” Clause 5 | # 6 | # Except as represented in this agreement, all work produced by Developer is 7 | # provided “AS IS”. Other than as provided in this agreement, Developer makes no 8 | # other warranties, express or implied, and hereby disclaims all implied warranties, 9 | # including any warranty of merchantability and warranty of fitness for a particular 10 | # purpose. 11 | ################################################################################## 12 | 13 | ################################################################################## 14 | # Date Completed: June 29, 2024 15 | # Author: John Bumgarner 16 | # 17 | # Date Revised: 18 | # Revised by: 19 | # 20 | # This Python script is designed to process, filter and analyze .pcap files using 21 | # the Python module PyShark. 22 | ################################################################################## 23 | 24 | ############################################################################################# 25 | # The Python module PyShark is a wrapper for the Wireshark CLI (TShark). 26 | # 27 | # reference: https://kiminewt.github.io/pyshark 28 | # reference: https://www.wireshark.org 29 | # reference: https://www.wireshark.org/docs/man-pages/tshark.html 30 | ############################################################################################# 31 | 32 | ############################################################################################### 33 | # Frame Data Elements 34 | # 35 | # frame.section_number: The section number in a multi-section capture file. 36 | # 37 | # frame.interface_id: The identifier for the network interface on which the packet was captured. 38 | # 39 | # frame.interface_name: The name of the network interface on which the packet was captured. 40 | # 41 | # frame.interface_description: A description of the network interface on which the packet was captured. 42 | # 43 | # frame.encap_type: The encapsulation type of the packet (link-layer header type). 44 | # 45 | # frame.time: The timestamp of the packet capture in local time. 46 | # 47 | # frame.time_utc: The timestamp of the packet capture in Coordinated Universal Time (UTC). 48 | # 49 | # frame.time_epoch The timestamp of the packet capture in epoch time (seconds since January 1, 1970). 50 | # 51 | # frame.offset_shift: The time offset shift applied to the packet timestamp. 52 | # 53 | # frame.time_delta: The time difference between this packet and the previous packet. 54 | # 55 | # frame.time_delta_displayed: The time difference displayed between this packet and the previous packet (may be 56 | # affected by display filters). 57 | # 58 | # frame.time_relative: The time relative to the beginning of the capture. 59 | # 60 | # frame.number: The frame number in the capture file. 61 | # 62 | # frame.len: The length of the packet on the wire (including all headers). 63 | # 64 | # frame.cap_len: The actual length of the captured packet in the capture file. 65 | # 66 | # frame.marked: Indicates whether the packet is marked for special attention by the user. 67 | # 68 | # frame.ignored: Indicates whether the packet is ignored in the analysis. 69 | # 70 | # frame.protocols: A list of protocols encapsulated in the packet. 71 | 72 | ################################################################################## 73 | # Python imports required for basic operations 74 | ################################################################################## 75 | # Standard library imports 76 | import logging 77 | # Third-party imports 78 | import pyshark 79 | 80 | # Configure logging 81 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 82 | 83 | def parse_frame_info(packet: pyshark.packet.packet.Packet) -> iter: 84 | """ 85 | Parses Frame information from the given packet. 86 | 87 | :param packet: A pyshark packet object. 88 | :type packet: pyshark.packet.packet.Packet 89 | 90 | :yields: Formatted Frame information. 91 | :rtype: iter of str 92 | """ 93 | try: 94 | if packet.frame_info: 95 | frame_interface_name = packet.frame_info.interface_name 96 | frame_interface_description = packet.frame_info.interface_description 97 | frame_time = packet.frame_info.time 98 | protocols = packet.frame_info.protocols 99 | yield {'frame_information: ' 100 | f'interface_name: {frame_interface_name}, ' 101 | f'interface_description: {frame_interface_description}, ' 102 | f'frame_time: {frame_time}, ' 103 | f'protocols: { protocols}'} 104 | except AttributeError: 105 | pass 106 | 107 | def filter_frame(network_interface: str) -> iter: 108 | """ 109 | Captures and filters packets from the specified network interface. 110 | 111 | :param network_interface: The network interface to capture packets from. 112 | :type network_interface: str 113 | 114 | :yields: Formatted Frame information. 115 | :rtype: iter of str 116 | """ 117 | capture = pyshark.LiveCapture(interface=network_interface) 118 | 119 | for packet in capture: 120 | yield from parse_frame_info(packet) 121 | 122 | def main(): 123 | """ 124 | Main function to capture and parse FRAME packet information. 125 | """ 126 | network_interface = 'en0' # Change to the appropriate interface name 127 | 128 | try: 129 | for frame_info in filter_frame(network_interface): 130 | if frame_info is not None: 131 | print(frame_info) 132 | except Exception as error: 133 | logging.error(f"An error occurred: {error}") 134 | 135 | if __name__ == "__main__": 136 | main() 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /examples/ftp_filtering_examples.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | ################################################################################## 4 | # “AS-IS” Clause 5 | # 6 | # Except as represented in this agreement, all work produced by Developer is 7 | # provided “AS IS”. Other than as provided in this agreement, Developer makes no 8 | # other warranties, express or implied, and hereby disclaims all implied warranties, 9 | # including any warranty of merchantability and warranty of fitness for a particular 10 | # purpose. 11 | ################################################################################## 12 | 13 | ################################################################################## 14 | # 15 | # Date Completed: February 15, 2020 16 | # Author: John Bumgarner 17 | # 18 | # Date Revised: June 15, 2024 19 | # Revised by: John Bumgarner 20 | # 21 | # This Python script is designed to process, filter and analyze .pcap files using 22 | # the Python module PyShark. 23 | ################################################################################## 24 | 25 | ############################################################################################# 26 | # The Python module PyShark is a wrapper for the Wireshark CLI (TShark). 27 | # 28 | # reference: https://kiminewt.github.io/pyshark 29 | # reference: https://www.wireshark.org 30 | # reference: https://www.wireshark.org/docs/man-pages/tshark.html 31 | ############################################################################################# 32 | 33 | import pyshark 34 | import logging 35 | 36 | # Configure logging 37 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 38 | 39 | def parse_ftp_info(packet: pyshark.packet.packet.Packet) -> iter: 40 | """ 41 | Parses FTP information from the given packet. 42 | 43 | :param packet: A pyshark packet object. 44 | :type packet: pyshark.packet.packet.Packet 45 | 46 | :yields: Formatted FTP request or response information. 47 | :rtype: iter of str 48 | """ 49 | try: 50 | if packet.ftp.command: 51 | source_address = packet.ip.src 52 | destination_address = packet.ip.dst 53 | ftp_command = packet.ftp.command 54 | yield f'FTP Command from {source_address} to {destination_address}: {ftp_command}' 55 | except AttributeError: 56 | pass 57 | 58 | try: 59 | if packet.ftp.response: 60 | source_address = packet.ip.src 61 | destination_address = packet.ip.dst 62 | ftp_response = packet.ftp.response 63 | yield f'FTP Response from {source_address} to {destination_address}: {ftp_response}' 64 | except AttributeError: 65 | pass 66 | 67 | def filter_ftp(network_interface: str, filter_type: str = 'transport_layer') -> iter: 68 | """ 69 | Captures and filters FTP packets from the specified network interface. 70 | 71 | :param network_interface: The network interface to capture packets from. 72 | :type network_interface: str 73 | 74 | :param filter_type: The type of filter to apply ('transport_layer', 'bpf', or 'display'). 75 | :type filter_type: str 76 | 77 | :yields: Formatted FTP request or response information. 78 | :rtype: iter of str 79 | """ 80 | if filter_type == 'transport_layer': 81 | capture = pyshark.LiveCapture(interface=network_interface) 82 | elif filter_type == 'bpf': 83 | capture = pyshark.LiveCapture(interface=network_interface, bpf_filter='tcp port 21') 84 | elif filter_type == 'display': 85 | capture = pyshark.LiveCapture(interface=network_interface, display_filter='ftp') 86 | else: 87 | raise ValueError("Invalid filter_type. Choose 'transport_layer', 'bpf', or 'display'.") 88 | 89 | for packet in capture: 90 | if filter_type == 'transport_layer' and not (hasattr(packet, 'tcp') and packet.tcp.dstport == '21'): 91 | continue 92 | yield from parse_ftp_info(packet) 93 | 94 | def main(): 95 | """ 96 | Main function to capture and print FTP packet information. 97 | """ 98 | network_interface = 'en0' # Change to the appropriate interface name 99 | filter_type = 'transport_layer' # Choose 'transport_layer', 'bpf', or 'display' 100 | 101 | try: 102 | for ftp_info in filter_ftp(network_interface, filter_type): 103 | if ftp_info is not None: 104 | print(ftp_info) 105 | except Exception as error: 106 | logging.error(f"An error occurred: {error}") 107 | 108 | if __name__ == "__main__": 109 | main() 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /examples/https_filtering_examples.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | ################################################################################## 4 | # “AS-IS” Clause 5 | # 6 | # Except as represented in this agreement, all work produced by Developer is 7 | # provided “AS IS”. Other than as provided in this agreement, Developer makes no 8 | # other warranties, express or implied, and hereby disclaims all implied warranties, 9 | # including any warranty of merchantability and warranty of fitness for a particular 10 | # purpose. 11 | ################################################################################## 12 | 13 | ################################################################################## 14 | # 15 | # Date Completed: February 15, 2020 16 | # Author: John Bumgarner 17 | # 18 | # Date Revised: June 15, 2024 19 | # Revised by: John Bumgarner 20 | # 21 | # This Python script is designed to process, filter and analyze .pcap files using 22 | # the Python module PyShark. 23 | ################################################################################## 24 | 25 | ############################################################################################# 26 | # The Python module PyShark is a wrapper for the Wireshark CLI (TShark). 27 | # 28 | # reference: https://kiminewt.github.io/pyshark 29 | # reference: https://www.wireshark.org 30 | # reference: https://www.wireshark.org/docs/man-pages/tshark.html 31 | ############################################################################################# 32 | import pyshark 33 | import logging 34 | 35 | # Configure logging 36 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 37 | 38 | 39 | def parse_tls_info(packet: pyshark.packet.packet.Packet) -> iter: 40 | """ 41 | Parses TLS (HTTPS) information from the given packet. 42 | 43 | :param packet: A pyshark packet object. 44 | :type packet: pyshark.packet.packet.Packet 45 | 46 | :yields: Formatted TLS (HTTPS) request or response information. 47 | :rtype: iter of str 48 | """ 49 | try: 50 | tls_info = {} 51 | if hasattr(packet, 'tls'): 52 | tls_data = packet.tls._all_fields 53 | if hasattr(packet.tls, 'segment.data'): 54 | tls_info['segment_data'] = tls_data.get('tls.segment.data') 55 | elif hasattr(packet.tls, 'handshake'): 56 | tls_info['tls_record'] = tls_data.get('tls.record') 57 | tls_info['record_content_type'] = tls_data.get('tls.record.content_type') 58 | tls_info['record version'] = tls_data.get('tls.record.version') 59 | tls_info['record_length'] = tls_data.get('tls.record.length') 60 | tls_info['handshake_version'] = tls_data.get('tls.handshake.version') 61 | tls_info['random_value'] = tls_data.get('tls.handshake.random') 62 | tls_info['cipher_suite'] = tls_data.get('tls.handshake.ciphersuite') 63 | tls_info['session_id'] = tls_data.get('tls.handshake.session_id') 64 | tls_info['extensions_length'] = tls_data.get('tls.handshake.extensions_length') 65 | tls_info['handshake_type'] = tls_data.get('tls.handshake.type') 66 | tls_info['cipher_suites'] = tls_data.get('tls.handshake.ciphersuites') 67 | tls_info['compression_methods'] = tls_data.get('tls.handshake.comp_methods') 68 | tls_info['extensions'] = tls_data.get('tls.handshake.extensions') 69 | tls_info['key_exchange'] = tls_data.get('tls.handshake.key_exchange') 70 | tls_info['certificate'] = tls_data.get('tls.handshake.certificate') 71 | elif not hasattr(packet.tls, 'handshake') and hasattr(packet.tls, 'app_data'): 72 | tls_info['tls_record'] = tls_data.get('tls.record') 73 | tls_info['record_content_type'] = tls_data.get('tls.record.content_type') 74 | tls_info['record_version'] = tls_data.get('tls.record.version') 75 | tls_info['record_length'] = tls_data.get('tls.record.length') 76 | tls_info['app_data'] = tls_data.get('tls.app_data') 77 | if not tls_info: 78 | yield 'No TLS (HTTPS) information in this packet' 79 | else: 80 | yield tls_info 81 | except AttributeError as e: 82 | pass 83 | 84 | def filter_tls(network_interface: str, filter_type: str = 'transport_layer') -> iter: 85 | """ 86 | Captures and filters HTTPS packets from the specified network interface. 87 | 88 | :param network_interface: The network interface to capture packets from. 89 | :type network_interface: str 90 | 91 | :param filter_type: The type of filter to apply ('transport_layer', 'bpf', or 'display'). 92 | :type filter_type: str 93 | 94 | :yields: Formatted TLS (HTTPS) request or response information. 95 | :rtype: iter of str 96 | """ 97 | if filter_type == 'transport_layer': 98 | capture = pyshark.LiveCapture(interface=network_interface) 99 | elif filter_type == 'bpf': 100 | capture = pyshark.LiveCapture(interface=network_interface, bpf_filter='tcp port 443') 101 | elif filter_type == 'display': 102 | capture = pyshark.LiveCapture(interface=network_interface, display_filter='tls') 103 | else: 104 | raise ValueError("Invalid filter_type. Choose 'transport_layer', 'bpf', or 'display'.") 105 | 106 | for packet in capture: 107 | if filter_type == 'transport_layer' and not (hasattr(packet, 'tcp') and packet.tcp.dstport == '443'): 108 | continue 109 | yield from parse_tls_info(packet) 110 | 111 | def main(): 112 | """ 113 | Main function to capture and print HTTPS packet information. 114 | """ 115 | network_interface = 'en0' # Change to the appropriate interface name 116 | filter_type = 'display' # Choose 'transport_layer', 'bpf', or 'display' 117 | 118 | try: 119 | for https_info in filter_tls(network_interface, filter_type): 120 | if 'No TLS (HTTPS) information in this packet' not in https_info: 121 | print(https_info) 122 | except Exception as error: 123 | logging.error(f"An error occurred: {error}") 124 | 125 | 126 | if __name__ == "__main__": 127 | main() 128 | -------------------------------------------------------------------------------- /examples/ip_filtering_examples.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | ################################################################################## 4 | # “AS-IS” Clause 5 | # 6 | # Except as represented in this agreement, all work produced by Developer is 7 | # provided “AS IS”. Other than as provided in this agreement, Developer makes no 8 | # other warranties, express or implied, and hereby disclaims all implied warranties, 9 | # including any warranty of merchantability and warranty of fitness for a particular 10 | # purpose. 11 | ################################################################################## 12 | 13 | ################################################################################## 14 | # Date Completed: July 04, 2024 15 | # Author: John Bumgarner 16 | # 17 | # Date Revised: 18 | # Revised by: 19 | # 20 | # This Python script is designed to process, filter and analyze .pcap files using 21 | # the Python module PyShark. 22 | ################################################################################## 23 | 24 | ############################################################################################# 25 | # The Python module PyShark is a wrapper for the Wireshark CLI (TShark). 26 | # 27 | # reference: https://kiminewt.github.io/pyshark 28 | # reference: https://www.wireshark.org 29 | # reference: https://www.wireshark.org/docs/man-pages/tshark.html 30 | ############################################################################################# 31 | 32 | ################################################################################## 33 | # Python imports required for basic operations 34 | ################################################################################## 35 | # Standard library imports 36 | import logging 37 | # Third-party imports 38 | import pyshark 39 | 40 | # Configure logging 41 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 42 | 43 | def parse_info(packet: pyshark.packet.packet.Packet) -> iter: 44 | """ 45 | Parses DNS information from the given packet. 46 | 47 | NOTE: this code is focused on DNS and can be changed to fit any use case. 48 | 49 | :param packet: A pyshark packet object. 50 | :type packet: pyshark.packet.packet.Packet 51 | 52 | :yields: Formatted DNS request or response information. 53 | :rtype: iter of str 54 | """ 55 | try: 56 | 57 | if hasattr(packet.dns, 'qry_name'): 58 | source_address = packet.ip.src 59 | destination_address = packet.ip.dst 60 | dns_location = packet.dns.qry_name 61 | query_type = packet.dns.qry_type 62 | query_class = packet.dns.qry_class 63 | yield (f'DNS Request from IP: {source_address}\n' 64 | f'Destination IP: {destination_address}\n' 65 | f'To DNS Name: {dns_location}\n' 66 | f'Query Type: {query_type}\n' 67 | f'Query Class: {query_class}') 68 | except AttributeError: 69 | pass 70 | try: 71 | if hasattr(packet.dns, 'resp_name'): 72 | source_address = packet.ip.src 73 | destination_address = packet.ip.dst 74 | dns_location = packet.dns.resp_name 75 | transaction_id = packet.dns.id 76 | response_code = packet.dns.flags_rcode 77 | answers = packet.dns.resp_addr 78 | yield (f'DNS Response from IP: {source_address}\n' 79 | f'Destination IP: {destination_address}\n' 80 | f'To DNS Name: {dns_location}\n' 81 | f'Transaction ID: {transaction_id}\n' 82 | f'Response Code: {response_code}\n' 83 | f'Answers: {answers}') 84 | except AttributeError: 85 | pass 86 | 87 | 88 | def filter_ips(network_interface: str, filter_type: str, source_ip_address: str, destination_ip_address: str) -> iter: 89 | """ 90 | Captures and filters DNS packet information based on either source or destination IP addresses or both. 91 | 92 | NOTE: this code is focused on DNS and can be changed to fit any use case. 93 | 94 | :param network_interface: The network interface to capture packets from. 95 | :type network_interface: str 96 | 97 | :param filter_type: The type of filter to apply ('src', 'dst', or 'both'). 98 | :type filter_type: str 99 | 100 | :param source_ip_address: The source IP address to filter on. 101 | :type source_ip_address: str 102 | 103 | :param destination_ip_address: The destination IP address to filter on. 104 | :type filter_type: str 105 | 106 | :yields: Formatted IP information. 107 | :rtype: iter of str 108 | """ 109 | if filter_type == 'src': 110 | capture = pyshark.LiveCapture(interface=network_interface, 111 | bpf_filter=f'ip and src host {source_ip_address}', 112 | display_filter='dns') 113 | elif filter_type == 'dst': 114 | capture = pyshark.LiveCapture(interface=network_interface, 115 | bpf_filter=f'ip and dst host {destination_ip_address}', 116 | display_filter='dns') 117 | elif filter_type == 'both': 118 | capture = pyshark.LiveCapture(interface=network_interface, 119 | bpf_filter=f'ip and src host {source_ip_address} ' 120 | f'and dst host {destination_ip_address}', 121 | display_filter='dns') 122 | else: 123 | raise ValueError("Invalid filter_type. Choose 'src', 'dst', or 'both'.") 124 | 125 | for packet in capture: 126 | yield from parse_info(packet) 127 | 128 | def main(): 129 | """ 130 | Main function to capture and print packet information based on either 131 | source or destination IP addresses or both. 132 | """ 133 | network_interface = 'en0' # Change to the appropriate interface name 134 | source_ip_address = '192.168.86.1' # Change to the appropriate IP Address 135 | destination_ip_address = '192.168.86.100' # Change to the appropriate IP Address 136 | filter_type = 'both' # Choose 'src', 'dst', or 'both' 137 | 138 | try: 139 | for info in filter_ips(network_interface, filter_type, source_ip_address, destination_ip_address): 140 | if info is not None: 141 | print(info) 142 | print('\n') 143 | except Exception as error: 144 | logging.error(f"An error occurred: {error}") 145 | 146 | if __name__ == "__main__": 147 | main() 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /examples/snmp_filtering_examples.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | ################################################################################## 4 | # “AS-IS” Clause 5 | # 6 | # Except as represented in this agreement, all work produced by Developer is 7 | # provided “AS IS”. Other than as provided in this agreement, Developer makes no 8 | # other warranties, express or implied, and hereby disclaims all implied warranties, 9 | # including any warranty of merchantability and warranty of fitness for a particular 10 | # purpose. 11 | ################################################################################## 12 | 13 | ################################################################################## 14 | # 15 | # Date Completed: February 15, 2020 16 | # Author: John Bumgarner 17 | # 18 | # Date Revised: June 15, 2024 19 | # Revised by: John Bumgarner 20 | # 21 | # This Python script is designed to process, filter and analyze .pcap files using 22 | # the Python module PyShark. 23 | ################################################################################## 24 | 25 | ############################################################################################# 26 | # The Python module PyShark is a wrapper for the Wireshark CLI (TShark). 27 | # 28 | # reference: https://kiminewt.github.io/pyshark 29 | # reference: https://www.wireshark.org 30 | # reference: https://www.wireshark.org/docs/man-pages/tshark.html 31 | ############################################################################################# 32 | import pyshark 33 | import logging 34 | 35 | # Configure logging 36 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 37 | 38 | 39 | def parse_snmp_info(packet: pyshark.packet.packet.Packet) -> iter: 40 | """ 41 | Parses SNMP information from the given packet. 42 | 43 | :param packet: A pyshark packet object. 44 | :type packet: pyshark.packet.packet.Packet 45 | 46 | :yields: SNMP packet information. 47 | :rtype: iter of str 48 | """ 49 | try: 50 | snmp_info = {} 51 | if hasattr(packet, 'snmp'): 52 | snmp_data = packet.snmp._all_fields 53 | snmp_info['message_version'] = snmp_data.get('snmp.msgVersion') 54 | snmp_info['message_id'] = snmp_data.get('snmp.msgID') 55 | snmp_info['message_max_size'] = snmp_data.get('snmp.msgMaxSize') 56 | snmp_info['message_flags'] = snmp_data.get('snmp.msgFlags') 57 | snmp_info['security_model'] = snmp_data.get('snmp.msgSecurityModel') 58 | snmp_info['authoritative_engine_id'] = snmp_data.get('snmp.msgAuthoritativeEngineID') 59 | snmp_info['authoritative_engine_boots'] = snmp_data.get('snmp.msgAuthoritativeEngineBoots') 60 | snmp_info['authoritative_engine_time'] = snmp_data.get('snmp.msgAuthoritativeEngineTime') 61 | snmp_info['user_name'] = snmp_data.get('snmp.msgUserName') 62 | snmp_info['authentication_parameters'] = snmp_data.get('snmp.msgAuthenticationParameters') 63 | snmp_info['privacy_parameters'] = snmp_data.get('snmp.msgPrivacyParameters') 64 | snmp_info['message_data'] = snmp_data.get('snmp.msgData') 65 | snmp_info['encrypted_pdu'] = snmp_data.get('snmp.encryptedPDU') 66 | if not snmp_info: 67 | yield 'No SNMP information in this packet' 68 | else: 69 | yield snmp_info 70 | except AttributeError as e: 71 | pass 72 | 73 | def filter_snmp(network_interface: str, filter_type: str = 'transport_layer') -> iter: 74 | """ 75 | Captures and filters SNMP packets from the specified network interface. 76 | 77 | :param network_interface: The network interface to capture packets from. 78 | :type network_interface: str 79 | 80 | :param filter_type: The type of filter to apply ('transport_layer', 'bpf', or 'display'). 81 | :type filter_type: str 82 | 83 | :yields: SNMP packet information. 84 | :rtype: iter of str 85 | """ 86 | if filter_type == 'transport_layer': 87 | capture = pyshark.LiveCapture(interface=network_interface) 88 | elif filter_type == 'bpf': 89 | capture = pyshark.LiveCapture(interface=network_interface, bpf_filter='udp port 161') 90 | elif filter_type == 'display': 91 | capture = pyshark.LiveCapture(interface=network_interface, display_filter='snmp') 92 | else: 93 | raise ValueError("Invalid filter_type. Choose 'transport_layer', 'bpf', or 'display'.") 94 | 95 | for packet in capture: 96 | if filter_type == 'transport_layer' and not (hasattr(packet, 'udp') and packet.udp.dstport == '161'): 97 | continue 98 | yield from parse_snmp_info(packet) 99 | 100 | def main(): 101 | """ 102 | Main function to capture and print SNMP packet information. 103 | """ 104 | network_interface = 'en0' # Change to the appropriate interface name 105 | filter_type = 'display' # Choose 'transport_layer', 'bpf', or 'display' 106 | 107 | try: 108 | for snmp_info in filter_snmp(network_interface, filter_type): 109 | if 'No SNMP information in this packet' not in snmp_info: 110 | print(snmp_info) 111 | except Exception as error: 112 | logging.error(f"An error occurred: {error}") 113 | 114 | if __name__ == "__main__": 115 | main() 116 | -------------------------------------------------------------------------------- /graphic/binary_funnel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnbumgarner/pyshark_usage_overview/501b21df36140cf86de5152b6910b15dcadc1fea/graphic/binary_funnel.jpg -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Project information 2 | site_name: PyShark Usage Documentation 3 | site_url: https://github.com/johnbumgarner/pyshark_usage_overview 4 | site_author: John Bumgarner 5 | site_description: "PyShark is a Python 3 module. PyShark is a wrapper for TShark, which allowing Python packet parsing using Wireshark dissectors." 6 | 7 | # Repository 8 | repo_name: johnbumgarner/pyshark_usage_overview 9 | repo_url: https://github.com/johnbumgarner/pyshark_usage_overview 10 | edit_uri: "" 11 | 12 | # Navigation Tree 13 | nav: 14 | - Home: index.md 15 | - Installation: installation.md 16 | - Usage: 17 | - Basic Usage: capture_usage/basic_usage.md 18 | - FileCapture Usage: capture_usage/file_capture_usage.md 19 | - LiveCapture Usage: capture_usage/live_capture_usage.md 20 | - Parameters: 21 | - FileCapture Parameters: parameters/file_capture_parameters.md 22 | - LiveCapture Parameters: parameters/live_capture_parameters.md 23 | - RemoteCapture Parameters: parameters/remote_capture_parameters.md 24 | - LiveRingCapture Parameters: parameters/livering_capture_parameters.md 25 | - InMemCapture Parameters: parameters/inmem_capture_parameters.md 26 | - PipeCapture Parameters: parameters/pipe_capture_parameters.md 27 | - Packet Layers: packet_layers.md 28 | - Parsing: 29 | - Ethernet Packets: parsing/eth_packets.md 30 | - IP Packets: parsing/ip_packets.md 31 | - TCP Packets: parsing/tcp_packets.md 32 | - UDP Packets: parsing/udp_packets.md 33 | - Decoding Packets: decoding/decode_packets.md 34 | - License: license.md 35 | 36 | # Configuration 37 | theme: 38 | name: material 39 | features: 40 | - navigation.tracking 41 | - navigation.expand 42 | - search.suggest 43 | - search.highlight 44 | - announce.dismiss 45 | palette: 46 | - scheme: default 47 | primary: indigo 48 | accent: deep orange 49 | toggle: 50 | icon: material/weather-sunny 51 | name: Switch to dark mode 52 | - scheme: slate 53 | primary: red 54 | accent: indigo 55 | toggle: 56 | icon: material/weather-night 57 | name: Switch to light mode 58 | font: 59 | text: Roboto 60 | code: Roboto Mono 61 | favicon: assets/favicon.png 62 | icon: 63 | logo: logo 64 | extra_css: 65 | - https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css 66 | - css/custom.css 67 | extra_javascript: 68 | - https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.js 69 | - js/highlight-init.js 70 | - js/custom.js 71 | - js/copy-code.js 72 | 73 | 74 | # Extensions 75 | markdown_extensions: 76 | - pymdownx.highlight: 77 | use_pygments: true 78 | - pymdownx.superfences 79 | - toc: 80 | title: On this page 81 | permalink: true 82 | permalink: 🔗 83 | permalink_title: Permalink to this headline 84 | 85 | 86 | # Extras 87 | extra: 88 | social: 89 | - icon: fontawesome/brands/github 90 | link: https://github.com/johnbumgarner 91 | 92 | # Plugins 93 | #plugins: 94 | # - git-revision-date-localized 95 | -------------------------------------------------------------------------------- /pcap_files/http2-h2c.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnbumgarner/pyshark_usage_overview/501b21df36140cf86de5152b6910b15dcadc1fea/pcap_files/http2-h2c.pcap -------------------------------------------------------------------------------- /pcap_files/traffic_flows_small.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnbumgarner/pyshark_usage_overview/501b21df36140cf86de5152b6910b15dcadc1fea/pcap_files/traffic_flows_small.pcap -------------------------------------------------------------------------------- /pyshark_packet_analysis.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | ################################################################################## 4 | # “AS-IS” Clause 5 | # 6 | # Except as represented in this agreement, all work produced by Developer is 7 | # provided “AS IS”. Other than as provided in this agreement, Developer makes no 8 | # other warranties, express or implied, and hereby disclaims all implied warranties, 9 | # including any warranty of merchantability and warranty of fitness for a particular 10 | # purpose. 11 | ################################################################################## 12 | 13 | ################################################################################## 14 | # 15 | # Date Completed: February 15, 2020 16 | # Author: John Bumgarner 17 | # 18 | # Date Revised: 19 | # Revised by: 20 | # 21 | # This Python script is designed to process, filter and analyze .pcap files using 22 | # the Python module PyShark. 23 | ################################################################################## 24 | 25 | ############################################################################################# 26 | # The Python module PyShark is a wrapper for the Wireshark CLI (TShark). 27 | # 28 | # reference: https://kiminewt.github.io/pyshark 29 | # reference: https://www.wireshark.org 30 | # reference: https://www.wireshark.org/docs/man-pages/tshark.html 31 | ############################################################################################# 32 | import pyshark 33 | 34 | 35 | def get_packet_details(packet): 36 | """ 37 | This function is designed to parse specific details from an individual packet. 38 | 39 | :param packet: raw packet from either a pcap file or via live capture using TShark 40 | :return: specific packet details 41 | """ 42 | protocol = packet.transport_layer 43 | source_address = packet.ip.src 44 | source_port = packet[packet.transport_layer].srcport 45 | destination_address = packet.ip.dst 46 | destination_port = packet[packet.transport_layer].dstport 47 | packet_time = packet.sniff_time 48 | return f'Packet Timestamp: {packet_time}' \ 49 | f'\nProtocol type: {protocol}' \ 50 | f'\nSource address: {source_address}' \ 51 | f'\nSource port: {source_port}' \ 52 | f'\nDestination address: {destination_address}' \ 53 | f'\nDestination port: {destination_port}\n' 54 | 55 | ############################################################################################# 56 | # This section is used to parse various types of protocols and their associated port numbers 57 | # from a standard Packet Capture (PCAP) file using PyShark. 58 | ############################################################################################# 59 | def filter_all_tcp_traffic_file(packet): 60 | """ 61 | This function is designed to parse all the Transmission Control Protocol(TCP) 62 | packets from a Packet Capture (PCAP) file. 63 | 64 | :param packet: raw packet from a pcap file 65 | :return: specific packet details 66 | """ 67 | if hasattr(packet, 'tcp'): 68 | results = get_packet_details(packet) 69 | return results 70 | 71 | 72 | def filter_all_udp_traffic_file(packet): 73 | """ 74 | This function is designed to parse all the User Datagram Protocol (UDP) 75 | packets from a Packet Capture (PCAP) file. 76 | 77 | :param packet: raw packet from a pcap file 78 | :return: specific packet details 79 | """ 80 | if hasattr(packet, 'udp'): 81 | results = get_packet_details(packet) 82 | return results 83 | 84 | 85 | def filter_dns_traffic_file(packet): 86 | """ 87 | This function is designed to parse all the Domain Name System (DNS) packets 88 | from a Packet Capture (PCAP) file. 89 | 90 | :param packet: raw packet from a pcap file 91 | :return: specific packet details 92 | """ 93 | if hasattr(packet, 'udp') and packet[packet.transport_layer].dstport == '53': 94 | results = get_packet_details(packet) 95 | return results 96 | 97 | 98 | def filter_ftp_traffic_file(packet): 99 | """ 100 | This function is designed to parse all the File Transfer Protocol (FTP) packets 101 | from a Packet Capture (PCAP) file. 102 | 103 | :param packet: raw packet from a pcap file 104 | :return: specific packet details 105 | """ 106 | if hasattr(packet, 'tcp') and packet[packet.transport_layer].dstport == '21': 107 | results = get_packet_details(packet) 108 | return results 109 | 110 | 111 | def filter_http_traffic_file(packet): 112 | """ 113 | This function is designed to parse all the Hypertext Transfer Protocol (HTTP) 114 | packets from a Packet Capture (PCAP) file. 115 | 116 | :param packet: raw packet from a pcap file 117 | :return: specific packet details 118 | """ 119 | if hasattr(packet, 'tcp') and packet[packet.transport_layer].dstport == '80': 120 | results = get_packet_details(packet) 121 | return results 122 | 123 | 124 | def filter_https_traffic_file(packet): 125 | """ 126 | This function is designed to parse all the Hypertext Transfer Protocol Secure (HTTPS) 127 | packets from a Packet Capture (PCAP) file. 128 | 129 | :param packet: raw packet from a pcap file 130 | :return: specific packet details 131 | """ 132 | if hasattr(packet, 'tcp') and packet[packet.transport_layer].dstport == '443': 133 | results = get_packet_details(packet) 134 | return results 135 | 136 | 137 | def filter_netbios_traffic_file(packet): 138 | """ 139 | This function is designed to parse all the Server Message Block (SMB) packets 140 | from a Packet Capture (PCAP) file. 141 | 142 | Port 139: SMB originally ran on top of NetBIOS using port 139. NetBIOS is an older 143 | transport layer that allows Windows computers to talk to each other on the same 144 | network. 145 | 146 | Port 445: Later versions of SMB (after Windows 2000) began to use port 445 on top of 147 | a TCP stack. 148 | 149 | :param packet: raw packet from a pcap file 150 | :return: specific packet details 151 | """ 152 | if hasattr(packet, 'tcp'): 153 | if packet[packet.transport_layer].dstport == '139' \ 154 | or packet[packet.transport_layer].dstport == '445': 155 | results = get_packet_details(packet) 156 | return results 157 | 158 | 159 | def filter_all_web_traffic_file(packet): 160 | """ 161 | This function is designed to parse all the Hypertext Transfer Protocol (HTTP) and 162 | Hypertext Transfer Protocol Secure (HTTPS) packets from a Packet Capture (PCAP) file. 163 | 164 | :param packet: raw packet from a pcap file. 165 | :return: specific packet details 166 | """ 167 | if hasattr(packet, 'tcp'): 168 | if packet[packet.transport_layer].dstport == '80' or packet[packet.transport_layer].dstport == '443': 169 | results = get_packet_details(packet) 170 | return results 171 | 172 | 173 | def get_file_captures(parse_type, pcap_file): 174 | capture = pyshark.FileCapture(pcap_file) 175 | for raw_packet in capture: 176 | if parse_type is 'dns': 177 | results = filter_dns_traffic_file(raw_packet) 178 | if results is not None: 179 | print(results) 180 | elif parse_type is 'ftp': 181 | results = filter_ftp_traffic_file(raw_packet) 182 | if results is not None: 183 | print(results) 184 | elif parse_type is 'https': 185 | results = filter_https_traffic_file(raw_packet) 186 | if results is not None: 187 | print(results) 188 | elif parse_type is 'http': 189 | results = filter_http_traffic_file(raw_packet) 190 | if results is not None: 191 | print(results) 192 | elif parse_type is 'netbios': 193 | results = filter_netbios_traffic_file(raw_packet) 194 | if results is not None: 195 | print(results) 196 | elif parse_type is 'tcp': 197 | results = filter_all_tcp_traffic_file(raw_packet) 198 | if results is not None: 199 | print(results) 200 | elif parse_type is 'udp': 201 | results = filter_all_udp_traffic_file(raw_packet) 202 | if results is not None: 203 | print(results) 204 | elif parse_type is 'web': 205 | results = filter_all_web_traffic_file(raw_packet) 206 | if results is not None: 207 | print(results) 208 | 209 | 210 | ############################################################################################# 211 | # This section is used to parse various types of protocols and their associated port numbers 212 | # from a live capture using TShark. 213 | ############################################################################################# 214 | def filter_dns_live_capture(packet): 215 | """ 216 | This function is designed to parse all the Domain Name System (DNS) packets 217 | from a live capture using TShark. 218 | 219 | :param packet: raw packet from a live capture using TShark 220 | :return: specific packet details 221 | """ 222 | if hasattr(packet, 'udp') and packet[packet.transport_layer].dstport == '53': 223 | try: 224 | if packet.dns.qry_name: 225 | source_address = packet.ip.src 226 | dns_location = packet.dns.qry_name 227 | return f'DNS Request from IP: {source_address}' \ 228 | f'\nTo DNS Name: {dns_location}' 229 | except AttributeError as e: 230 | pass 231 | 232 | try: 233 | if packet.dns.resp_name: 234 | source_address = packet.ip.src 235 | dns_location = packet.dns.resp_name 236 | return f'DNS Response from IP: {source_address}' \ 237 | f'\nTo DNS Name: {dns_location}' 238 | except AttributeError as e: 239 | pass 240 | 241 | 242 | def filter_all_web_traffic_file(packet): 243 | """ 244 | This function is designed to parse all the Hypertext Transfer Protocol (HTTP) and 245 | Hypertext Transfer Protocol Secure (HTTPS) packets from a live capture using TShark. 246 | 247 | :param packet: raw packet from a live capture using TShark 248 | :return: specific packet details 249 | """ 250 | if hasattr(packet, 'tcp'): 251 | if packet[packet.transport_layer].dstport == '80' or packet[packet.transport_layer].dstport == '443': 252 | results = get_packet_details(packet) 253 | return results 254 | 255 | 256 | def filter_https_live_packet_capture(packet): 257 | """ 258 | This function is designed to parse all the Hypertext Transfer Protocol Secure (HTTPS) 259 | packets from a live capture using TShark. 260 | 261 | :param packet: raw packet from a live capture using TShark 262 | :return: specific packet details 263 | """ 264 | if hasattr(packet, 'tcp') and packet[packet.transport_layer].dstport == '443': 265 | results = get_packet_details(packet) 266 | return results 267 | 268 | 269 | def filter_http_live_packet_capture(packet): 270 | """ 271 | This function is designed to parse all the Hypertext Transfer Protocol (HTTP) 272 | packets from a live capture using TShark. 273 | 274 | :param packet: raw packet from a live capture using TShark 275 | :return: specific packet details 276 | """ 277 | if hasattr(packet, 'tcp') and packet[packet.transport_layer].dstport == '80': 278 | results = get_packet_details(packet) 279 | return results 280 | 281 | 282 | def filter_ssh_live_packet_capture(packet): 283 | """ 284 | This function is designed to parse all the Secure Shell (SSH) packets 285 | from a live capture using TShark. 286 | 287 | :param packet: raw packet from a live capture using TShark 288 | :return: specific packet details 289 | """ 290 | if hasattr(packet, 'tcp') and packet[packet.transport_layer].dstport == '22': 291 | results = get_packet_details(packet) 292 | return results 293 | 294 | 295 | def filter_ftp_live_packet_capture(packet): 296 | """ 297 | This function is designed to parse all the File Transfer Protocol (FTP) packets 298 | from a live capture using TShark. 299 | 300 | :param packet: raw packet from a live capture using TShark 301 | :return: specific packet details 302 | """ 303 | if hasattr(packet, 'tcp') and packet[packet.transport_layer].dstport == '21': 304 | results = get_packet_details(packet) 305 | return results 306 | 307 | 308 | def get_live_captures(parse_type, network_interface): 309 | capture = pyshark.LiveCapture(interface=network_interface) 310 | capture.sniff(timeout=50) 311 | for raw_packet in capture.sniff_continuously(): 312 | if parse_type is 'dns': 313 | results = filter_dns_live_capture(raw_packet) 314 | if results is not None: 315 | print(results) 316 | elif parse_type is 'ftp': 317 | results = filter_ftp_live_packet_capture(raw_packet) 318 | if results is not None: 319 | print(results) 320 | elif parse_type is 'https': 321 | results = filter_https_live_packet_capture(raw_packet) 322 | if results is not None: 323 | print(results) 324 | elif parse_type is 'http': 325 | results = filter_http_live_packet_capture(raw_packet) 326 | if results is not None: 327 | print(results) 328 | elif parse_type is 'ssh': 329 | results = filter_ssh_live_packet_capture(raw_packet) 330 | if results is not None: 331 | print(results) 332 | elif parse_type is 'web': 333 | results = filter_all_web_traffic_file(raw_packet) 334 | if results is not None: 335 | print(results) 336 | 337 | 338 | ############################################################################################# 339 | # This section is used to parse various types of protocols and their associated port numbers 340 | # from a standard Packet Capture (PCAP) file using PyShark and a live capture using TShark. 341 | # 342 | # display_filter='tcp.analysis.retransmission' 343 | # TCP Analysis Flags 344 | # Expert Info (Note/Sequence): This frame is a (suspected) retransmission 345 | # This frame is a (suspected) retransmission 346 | # 347 | # # display_filter='tcp.analysis.fast_retransmission' 348 | # TCP Analysis Flags 349 | # This frame is a (suspected) fast retransmission 350 | # This frame is a (suspected) retransmission 351 | # Expert Info (Note/Sequence): This frame is a (suspected) fast retransmission 352 | # Expert Info (Note/Sequence): This frame is a (suspected) retransmission 353 | ############################################################################################# 354 | def filter_retransmission_packet_file(packet, show_packets=''): 355 | counter = 0 356 | if not show_packets: 357 | counter += 1 358 | return '*' * 10, f'Retransmission packet {counter}:', '*' * 10 359 | elif show_packets: 360 | protocol = packet.transport_layer 361 | source_address = packet.ip.src 362 | source_port = packet[packet.transport_layer].srcport 363 | destination_address = packet.ip.dst 364 | destination_port = packet[packet.transport_layer].dstport 365 | packet_time = packet.sniff_time 366 | 367 | if "(suspected) retransmission" in str(packet.tcp) \ 368 | and "(suspected) spurious retransmission" in str(packet.tcp): 369 | return f'Suspected spurious retransmission' \ 370 | f'\nPacket Timestamp: {packet_time}' \ 371 | f'\nProtocol type: {protocol}' \ 372 | f'\nSource address: {source_address}' \ 373 | f'\nSource port: {source_port}' \ 374 | f'\nDestination address: {destination_address}' \ 375 | f'\nDestination port: {destination_port}\n' 376 | 377 | elif "(suspected) retransmission" in str(packet.tcp) \ 378 | and "suspected retransmission" not in str(packet.tcp): 379 | return f'Suspected retransmission' \ 380 | f'\nPacket Timestamp: {packet_time}' \ 381 | f'\nProtocol type: {protocol}' \ 382 | f'\nSource address: {source_address}' \ 383 | f'\nSource port: {source_port}' \ 384 | f'\nDestination address: {destination_address}' \ 385 | f'\nDestination port: {destination_port}\n' 386 | 387 | 388 | def filter_retransmission_live_capture(packet, show_packets=''): 389 | counter = 0 390 | if not show_packets: 391 | counter += 1 392 | return '*' * 10, f'Retransmission packet {counter}:', '*' * 10 393 | elif show_packets: 394 | protocol = packet.transport_layer 395 | source_address = packet.ip.src 396 | source_port = packet[packet.transport_layer].srcport 397 | destination_address = packet.ip.dst 398 | destination_port = packet[packet.transport_layer].dstport 399 | packet_time = packet.sniff_time 400 | 401 | if "(suspected) retransmission" in str(packet.tcp) \ 402 | and "(suspected) spurious retransmission" in str(packet.tcp): 403 | 404 | return f'Suspected spurious retransmission' \ 405 | f'\nPacket Timestamp: {packet_time}' \ 406 | f'\nProtocol type: {protocol}' \ 407 | f'\nSource address: {source_address}' \ 408 | f'\nSource port: {source_port}' \ 409 | f'\nDestination address: {destination_address}' \ 410 | f'\nDestination port: {destination_port}\n' 411 | 412 | elif "(suspected) retransmission" in str(packet.tcp) \ 413 | and "suspected retransmission" not in str(packet.tcp): 414 | return f'Suspected retransmission' \ 415 | f'\nPacket Timestamp: {packet_time}' \ 416 | f'\nProtocol type: {protocol}' \ 417 | f'\nSource address: {source_address}' \ 418 | f'\nSource port: {source_port}' \ 419 | f'\nDestination address: {destination_address}' \ 420 | f'\nDestination port: {destination_port}\n' 421 | 422 | 423 | def get_retransmissions(parse_type, pcap_file, network_interface): 424 | 425 | if parse_type is 'file': 426 | capture = pyshark.FileCapture(pcap_file, display_filter='tcp.analysis.retransmission') 427 | for raw_packet in capture: 428 | results = filter_retransmission_packet_file(raw_packet, 'True') 429 | if results is not None: 430 | print(results) 431 | 432 | elif parse_type is 'live': 433 | capture = pyshark.LiveCapture(interface=network_interface, display_filter='tcp.analysis.retransmission') 434 | capture.sniff(timeout=50) 435 | for raw_packet in capture.sniff_continuously(): 436 | results = filter_retransmission_packet_file(raw_packet, 'True') 437 | if results is not None: 438 | print(results) 439 | 440 | 441 | ############################################################################################# 442 | # This section is used to parse all the Uniform Resource Locators (URLs) from a standard 443 | # Packet Capture (PCAP) file using PyShark. 444 | ############################################################################################# 445 | def filter_all_urls_file(packet): 446 | if hasattr(packet, 'http'): 447 | field_names = packet.http._all_fields 448 | field_values = packet.http._all_fields.values() 449 | for field_name in field_names: 450 | for field_value in field_values: 451 | if field_name == 'http.request.full_uri' and field_value.startswith('http'): 452 | return field_value 453 | 454 | 455 | def get_urls_file_captures(pcap_file): 456 | capture = pyshark.FileCapture(pcap_file) 457 | for raw_packet in capture: 458 | url = filter_all_urls_file(raw_packet) 459 | if url is not None: 460 | print(url) 461 | 462 | 463 | def main(): 464 | 465 | # PCAP file to parse 466 | pcap_file = 'traffic_flows_small.pcap' 467 | 468 | # Network interface used by TShark for live capture 469 | network_interface = 'en0' 470 | 471 | # Parse types include: tcp, udp, dns, ftp, http, https, 472 | # netbios, ssh, web (which includes http & https) 473 | get_file_captures('http', pcap_file) 474 | 475 | # Parse types include: dns, ftp, http, https, 476 | # ssh, web (which includes http & https) 477 | # get_live_captures('ftp', network_interface) 478 | 479 | # Parse types include: file and live. 480 | # get_retransmissions('file', pcap_file, network_interface) 481 | 482 | # Prases all the Uniform Resource Locators (URLs) from 483 | # a PCAP file. 484 | # get_urls_file_captures(pcap_file) 485 | 486 | 487 | if __name__ == "__main__": 488 | main() 489 | -------------------------------------------------------------------------------- /readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Required 2 | # Required 3 | version: 2 4 | 5 | build: 6 | os: ubuntu-22.04 7 | tools: 8 | python: "3.9" 9 | 10 | mkdocs: 11 | configuration: mkdocs.yml 12 | 13 | # Optionally declare the Python requirements required to build your docs 14 | python: 15 | install: 16 | - requirements: docs/requirements.txt --------------------------------------------------------------------------------