<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Diplomats can code too! (Posts about generic dissectors)</title><link>https://wintermade.it/blog/</link><description></description><atom:link href="https://wintermade.it/blog/categories/generic-dissectors.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Sat, 05 Oct 2019 08:14:28 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>How to write generic dissectors in Wireshark</title><link>https://wintermade.it/blog/posts/how-to-write-generic-dissectors-in-wireshark.html</link><dc:creator>Alessandro Balzano</dc:creator><description>&lt;div&gt;&lt;p&gt;Wireshark is a flexible network analyzer, that can also be
extended via plugins or dissectors.&lt;/p&gt;
&lt;p&gt;A dissector is a kind of plugin that lets Wireshark
understand a protocol - in our case, a protocol that is only used
by a certain application.
There are several reasons to create your own (application-level) protocol over UDP/IP or TCP/IP,
such as efficiency (by sending only binary data, formatted in a certain application-specific format).&lt;/p&gt;
&lt;p&gt;Wireshark is a very helpful tool during system integration tests,
or while developing a networked application. A dissector helps
developers and testers check if the applications under test
are sending (or receiving) data correctly - if the structure of a certain message
is as defined by the protocol, if some fields have invalid values,
if an application is sending more (or fewer) messages than expected in
a certain timeframe.&lt;/p&gt;
&lt;div class="section" id="wireshark-generic-dissectors-a-declarative-approach"&gt;
&lt;h2&gt;WireShark Generic Dissectors - a declarative approach&lt;/h2&gt;
&lt;p&gt;Wireshark Generic Dissectors (WSGD) is a plugin that lets you define a dissector
for your custom protocol, in a declarative manner.&lt;/p&gt;
&lt;p&gt;Being declarative is a cool idea - by just saying &lt;em&gt;what&lt;/em&gt; the protocol looks like,
the content of the dissector is clear to a technical, but non-developer, user.
Such protocol descriptions can also be used as documentation, without having to manage
different Wireshark API versions (as it may happen with Lua-based dissectors).
It's not all fun and games though: this plugin has some (reasonable) &lt;a class="reference external" href="http://wsgd.free.fr/faq.html"&gt;limitations&lt;/a&gt;,
such as not managing text protocols, or requiring an header common to every kind of message
described in the protocol.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="let-s-write-a-generic-dissector"&gt;
&lt;h2&gt;Let's write a generic dissector&lt;/h2&gt;
&lt;p&gt;Let's start with the Wireshark Generic Dissector file: it contains some metadata about the protocol.
These metadata, consisting of details such as the protocol name, the structure that sketches the header of
all messages in the protocol and the main message, are necessary to be efficient when parsing the messages
during the capture.&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_2daba95336d24370807dcfe614588395-1"&gt;&lt;/a&gt;# file custom.wsgd
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-2"&gt;&lt;/a&gt;
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-3"&gt;&lt;/a&gt;# protocol metadata
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-4"&gt;&lt;/a&gt;PROTONAME Custom Protocol over UDP
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-5"&gt;&lt;/a&gt;PROTOSHORTNAME Custom
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-6"&gt;&lt;/a&gt;PROTOABBREV custom
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-7"&gt;&lt;/a&gt;
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-8"&gt;&lt;/a&gt;# conditions on which the dissector is applied:
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-9"&gt;&lt;/a&gt;# the protocol will be applied on all UDP messages with port = 8756
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-10"&gt;&lt;/a&gt;PARENT_SUBFIELD udp.port
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-11"&gt;&lt;/a&gt;PARENT_SUBFIELD_VALUES 8756
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-12"&gt;&lt;/a&gt;
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-13"&gt;&lt;/a&gt;# the name of the header structure
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-14"&gt;&lt;/a&gt;MSG_HEADER_TYPE                    T_custom_header
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-15"&gt;&lt;/a&gt;# field which permits to identify the message type.
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-16"&gt;&lt;/a&gt;MSG_ID_FIELD_NAME                  msg_id
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-17"&gt;&lt;/a&gt;# the main message type - usually it is a fake message, built of one
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-18"&gt;&lt;/a&gt;#    of the possible messages
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-19"&gt;&lt;/a&gt;MSG_MAIN_TYPE                      T_custom_switch(msg_id)
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-20"&gt;&lt;/a&gt;
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-21"&gt;&lt;/a&gt;# this token marks the end of the protocol description
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-22"&gt;&lt;/a&gt;PROTO_TYPE_DEFINITIONS
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-23"&gt;&lt;/a&gt;
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-24"&gt;&lt;/a&gt;# refer to the description of the data format
&lt;a name="rest_code_2daba95336d24370807dcfe614588395-25"&gt;&lt;/a&gt;include custom.fdesc;
&lt;/pre&gt;&lt;p&gt;The second file is the data format description: it described the messages of the protocol we're writing a dissector for.&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-1"&gt;&lt;/a&gt;# file custom.fdesc
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-2"&gt;&lt;/a&gt;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-3"&gt;&lt;/a&gt;# here, we define an enumerated type to list the type of messages
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-4"&gt;&lt;/a&gt;#   defined in our protocol
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-5"&gt;&lt;/a&gt;enum8 T_custom_msg_type
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-6"&gt;&lt;/a&gt;{
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-7"&gt;&lt;/a&gt;    word_message   0
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-8"&gt;&lt;/a&gt;    number_message 1
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-9"&gt;&lt;/a&gt;}
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-10"&gt;&lt;/a&gt;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-11"&gt;&lt;/a&gt;# here, we define the structure of the header.
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-12"&gt;&lt;/a&gt;# The header (the same for each message type) must...
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-13"&gt;&lt;/a&gt;struct T_custom_header
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-14"&gt;&lt;/a&gt;{
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-15"&gt;&lt;/a&gt;    # ... define the order of the data
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-16"&gt;&lt;/a&gt;    byte_order big_endian;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-17"&gt;&lt;/a&gt;    uint32 counter;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-18"&gt;&lt;/a&gt;    uint8  size_after_header;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-19"&gt;&lt;/a&gt;    # ... contain the field defined as MSG_ID_FIELD_NAME
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-20"&gt;&lt;/a&gt;    T_custom_msg_type msg_id;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-21"&gt;&lt;/a&gt;}
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-22"&gt;&lt;/a&gt;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-23"&gt;&lt;/a&gt;struct T_word_message
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-24"&gt;&lt;/a&gt;{
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-25"&gt;&lt;/a&gt;    T_custom_header header;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-26"&gt;&lt;/a&gt;    uint8           word_len;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-27"&gt;&lt;/a&gt;    # array of characters
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-28"&gt;&lt;/a&gt;    char[word_len]  word;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-29"&gt;&lt;/a&gt;    # "word" messages will always have some unused trailing bytes:
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-30"&gt;&lt;/a&gt;    #   they can be marked as raw(*) - the size is calculated at runtime
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-31"&gt;&lt;/a&gt;    raw(*)          spare;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-32"&gt;&lt;/a&gt;}
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-33"&gt;&lt;/a&gt;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-34"&gt;&lt;/a&gt;struct T_number_message
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-35"&gt;&lt;/a&gt;{
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-36"&gt;&lt;/a&gt;    T_custom_header header;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-37"&gt;&lt;/a&gt;    uint8           number;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-38"&gt;&lt;/a&gt;    bool8           is_even;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-39"&gt;&lt;/a&gt;}
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-40"&gt;&lt;/a&gt;
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-41"&gt;&lt;/a&gt;# T_custom_switch is the main message (as defined in the protocol description)
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-42"&gt;&lt;/a&gt;# according to the parameter msg_id (of type T_custom_msg_type), we define
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-43"&gt;&lt;/a&gt;# the main message to be defined by a single message: either T_word_message or T_number_message.
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-44"&gt;&lt;/a&gt;switch T_custom_switch T_custom_msg_type
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-45"&gt;&lt;/a&gt;{
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-46"&gt;&lt;/a&gt;case T_custom_msg_type::word_message:   T_word_message "";
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-47"&gt;&lt;/a&gt;case T_custom_msg_type::number_message: T_number_message "";
&lt;a name="rest_code_a5d4301114634ce4a4b287ecac5e602b-48"&gt;&lt;/a&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="generating-some-network-traffic"&gt;
&lt;h2&gt;Generating some network traffic...&lt;/h2&gt;
&lt;p&gt;To verify that the dissector we've written is correct,
we are going to build a small client to send some UDP messages to a very simple
server.&lt;/p&gt;
&lt;p&gt;Let's start with the server: it just receives UDP messages on port 8756, and
prints the contents of those messages.&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-1"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socketserver&lt;/span&gt;
&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-2"&gt;&lt;/a&gt;
&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socketserver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DatagramRequestHandler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-4"&gt;&lt;/a&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-5"&gt;&lt;/a&gt;        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-6"&gt;&lt;/a&gt;        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-7"&gt;&lt;/a&gt;
&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-8"&gt;&lt;/a&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-9"&gt;&lt;/a&gt;    &lt;span class="n"&gt;serv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socketserver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UDPServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8756&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;CustomHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_7282ee3ccb1c4420ac57bc41000219e4-10"&gt;&lt;/a&gt;    &lt;span class="n"&gt;serv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The client sends some data to our server - we just need it to generate some traffic to sniff on Wireshark.&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-1"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-2"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;struct&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-3"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-4"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-5"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-6"&gt;&lt;/a&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-7"&gt;&lt;/a&gt;&lt;span class="n"&gt;HOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8756&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-8"&gt;&lt;/a&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-9"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# SOCK_DGRAM is the socket type to use for UDP sockets&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-10"&gt;&lt;/a&gt;&lt;span class="n"&gt;sock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOCK_DGRAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-11"&gt;&lt;/a&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-12"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# refer to `pydoc struct`&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-13"&gt;&lt;/a&gt;&lt;span class="n"&gt;HEADER_STRUCT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-14"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# network byte order&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-15"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"L"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# counter&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-16"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# message size&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-17"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# message type (0: word, 1: number)&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-18"&gt;&lt;/a&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-19"&gt;&lt;/a&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-20"&gt;&lt;/a&gt;&lt;span class="n"&gt;PAYLOAD_WORD_TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HEADER_STRUCT&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-21"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;# word length&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-22"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"100s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# string (at most 100 characters)&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-23"&gt;&lt;/a&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-24"&gt;&lt;/a&gt;&lt;span class="n"&gt;word_struct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PAYLOAD_WORD_TYPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-25"&gt;&lt;/a&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-26"&gt;&lt;/a&gt;&lt;span class="n"&gt;PAYLOAD_NUMBER_TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HEADER_STRUCT&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-27"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# number&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-28"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# 0: even, 1: odd&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-29"&gt;&lt;/a&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-30"&gt;&lt;/a&gt;&lt;span class="n"&gt;number_struct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PAYLOAD_NUMBER_TYPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-31"&gt;&lt;/a&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-32"&gt;&lt;/a&gt;&lt;span class="n"&gt;msg_counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-33"&gt;&lt;/a&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-34"&gt;&lt;/a&gt;    &lt;span class="n"&gt;msg_counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-35"&gt;&lt;/a&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-36"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;# prepare data to send&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-37"&gt;&lt;/a&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.70&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-38"&gt;&lt;/a&gt;        &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-39"&gt;&lt;/a&gt;        &lt;span class="n"&gt;is_even&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-40"&gt;&lt;/a&gt;        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number_struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_even&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-41"&gt;&lt;/a&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-42"&gt;&lt;/a&gt;        &lt;span class="n"&gt;string_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-43"&gt;&lt;/a&gt;        &lt;span class="n"&gt;the_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ascii_letters&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_len&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="s2"&gt;"ascii"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-44"&gt;&lt;/a&gt;        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;word_struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;the_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-45"&gt;&lt;/a&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-46"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;# send the message&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-47"&gt;&lt;/a&gt;    &lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sendto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-48"&gt;&lt;/a&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-49"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;# wait 200ms&lt;/span&gt;
&lt;a name="rest_code_0ac7d6ccc8b342fabf87e75b1ce0c0a7-50"&gt;&lt;/a&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="set-it-up"&gt;
&lt;h2&gt;Set it up&lt;/h2&gt;
&lt;p&gt;Wireshark Generic Dissector is a binary plugin, distributed as a .so file - please read the &lt;a class="reference external" href="http://wsgd.free.fr/installation.html"&gt;installation procedure&lt;/a&gt;.
I've summarized what I did to install the plugin and the files we've written so far:&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-1"&gt;&lt;/a&gt;# download the plugin - be sure it's the right one for
&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-2"&gt;&lt;/a&gt;# the version of Wireshark installed on your system
&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-3"&gt;&lt;/a&gt;wget http://wsgd.free.fr/300X/generic.so.ubuntu.64.300X.tar.gz
&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-4"&gt;&lt;/a&gt;# extract the file generic.so
&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-5"&gt;&lt;/a&gt;unzip ./generic.so.ubuntu.64.300X.tar.gz
&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-6"&gt;&lt;/a&gt;# install the shared object globally by putting in the right folder
&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-7"&gt;&lt;/a&gt;sudo cp generic.so  /usr/lib/wireshark/plugins/3.0/epan
&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-8"&gt;&lt;/a&gt;# install the dissector files in the right folder - the same of the shared object
&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-9"&gt;&lt;/a&gt;sudo cp custom.wsgd /usr/lib/wireshark/plugins/3.0/epan
&lt;a name="rest_code_46e510ef0f054a1eac235118a04f0c29-10"&gt;&lt;/a&gt;sudo cp custom.fdesc /usr/lib/wireshark/plugins/3.0/epan
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="test-drive"&gt;
&lt;h2&gt;Test drive&lt;/h2&gt;
&lt;img alt="/images/wireshark-wsgd-with-dissector.png" src="https://wintermade.it/blog/images/wireshark-wsgd-with-dissector.png"&gt;
&lt;p&gt;As we can see by the screenshot, we are now able to see the content of the messages our application
is sending to the server, without writing a single line of code (other than our application,
obviously).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Wireshark Generic Dissector project homepage: &lt;a class="reference external" href="http://wsgd.free.fr/index.html"&gt;http://wsgd.free.fr/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;WSGD file description: &lt;a class="reference external" href="http://wsgd.free.fr/wsgd_format.html"&gt;http://wsgd.free.fr/wsgd_format.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Data format description (fdesc): &lt;a class="reference external" href="http://wsgd.free.fr/fdesc_format.html"&gt;http://wsgd.free.fr/fdesc_format.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class="docutils"&gt;
&lt;p&gt;If you feel that this article helped you, feel free to share it! If you have questions, ask on &lt;a class="reference external" href="https://twitter.com/alfateam123"&gt;Twitter&lt;/a&gt;,
or offer me a &lt;a class="reference external" href="https://ko-fi.com/alessandrobalzano"&gt;coffee&lt;/a&gt; to let me keep writing these notes!&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>generic dissectors</category><category>python</category><category>wireshark</category><guid>https://wintermade.it/blog/posts/how-to-write-generic-dissectors-in-wireshark.html</guid><pubDate>Sat, 27 Apr 2019 09:00:12 GMT</pubDate></item></channel></rss>