Development/sharkd

Introduction

sharkd is a program that makes the powerful dissection and analysis capabilities of Wireshark available via a programmatic interface. A program can send simple JSON-format requests to sharkd to load, analyse and manipulate network packet files.

Many of the functions that we see in the standard Wireshark user interface are available via sharkd including packet protocol tree, packet bytes and display filters.

The wiki page sharkd Request Syntax gives full details of the request types and their parameters.

Installation

The sharkd executable is not included in the standard Wireshark binary package (Windows MSI, etc.) and so must be built from source. Building sharkd under Windows results in a sharkd.exe executable.

sharkd will not work with just the sharkd.exe file; it uses Wireshark DLLs and preference files. Therefore, we need to install everything that results from a build of sharkd.

Running sharkd

We can run sharkd in two modes:

Multiple sessions can connect to sharkd running in Daemon Mode. A dedicated sharkd.exe process is spun up for each connection. Therefore, when there are no connections there is a single sharkd process, when there is one active session there are two sharkd processes, when a second connection is made there will be three sharkd processes, and so on.

There are two command line option formats; Classic (the original format) and POSIX. The POSIX format attempts to follow the POSIX command line standard and offers more options. We refer to the POSIX extended range of options as the Gold options.

Classic

To start sharkd in Console Mode use the command:

  sharkd -

Note: the default compilations only support tcp ports on Windows.
See Which package contains sharkd? and Add sharkd - daemon variant

Peter Wu | Jan 24, 2017 | Patch Set 8: Code-Review+1
Should be a good start. (Disabling the TCP socket also removes my concern about remote attacks.)

To start sharkd in Daemon Mode running on a TCP port, use the command:

  sharkd tcp:127.0.0.1:4446

This will result in sharkd listening for TCP connections to localhost TCP port 4446. You can change the TCP port number if necessary.

UNIX sockets are also supported:

  sharkd unix:/tmp/sharkd.sock

In this case, sharkd always uses the preferences set in the Default profile. sharkd obeys other aspects of the Default profile such as disabled_protos, enabled_protos, etc.

Gold

Gold (gold_options):
  -a <socket>, --api <socket>
                           listen on this socket
  -h, --help               show this help information
  -v, --version            show version information
  -C <config profile>, --config-profile <config profile>
                           start with specified configuration profile

  Examples:
    sharkd -C myprofile
    sharkd -a tcp:127.0.0.1:4446 -C myprofile

If you change any preferences in the selected profile (by editing the preferences file or using Wireshark Edit -> Preferences) the changes will not take effect in any current sharkd sessions. You will need to start a new session.

sharkd obeys other aspects of the selected profile such as disabled_protos, enabled_protos, etc.

sharkd Requests

Request Syntax

sharkd service requests have the general format:

  {"req":"command","_option_":"_value_","_option_":"_value_",...}

The request processor uses a simple gets(...) function to read incoming requests. This means that:

The commands must be in lower case as shows below. Quotes around keys and values must be double quotes - single quotes produce a JSON error. Also note the use of the UK English spelling of analyse; analyze won't work.

If you send invalid JSON on the connection, sharkd writes the stdout message:

  invalid JSON -> closing

and sharkd session terminates.

Request Types

The request types are:

Entering JSON requests through the Console Interface sometimes generates additional stdout messages as well as the JSON response, for example:

{"req":"load","file":"c:/traces/Contoso_01/web01/web01_00001_20161012151754.pcapng"}
load: filename=c:/traces/Contoso_01/web01/web01_00001_20161012151754.pcapng
{"err":0}

The wiki page sharkd Request Syntax gives full details of the request types and their parameters.

Bugs

During experimentation with sharkd, a few bugs were discovered that are noteworthy.

Exception if File Not Loaded

Issuing commands to interrogate or modify a packet file before loading any file often results in a program exception.

Exception if Backslash is Not Escaped

The Windows file path backslash (\) separator must be escaped, and if they are not, this too results in a program exception. Alternatively, forward slashes can be used as shown in the load request example above.

Unexpected Results

sharkd will sometimes produce unexpected results:

Studying and Debugging sharkd

Many will want to use Visual Studio to study the way sharkd works or for debugging. Remember that when running in Daemon Mode, the JSON requests will be processed by a dedicated sharkd process, and not the one you start executing in Visual Studio. The simplest way to avoid this situation is to study or debug when running in Console Mode.

When a file is loaded into Wireshark, the protocol dissectors are called once for every packet in the PCAPNG file, and then called at least once more as the packets are displayed. This is also true with sharkd:

Testing with Putty

Suitable putty settings are:

When you successfully connect, the daemon writes a stdout message:

  Hello in child.

Simple Python Code Example

This program connects to sharkd running in Daemon mode, sends two commands, displays the response for each and then closes the connection.

import socket

def get_json_bytes(json_string):
    return bytes((json_string + '\n'), 'utf-8')

def json_send_recv(s, json) -> str:
    s.sendall(get_json_bytes(json))
    data = s.recv(1024)
    return data[:-4].decode('utf-8')

host = socket.gethostbyname('localhost')
port = 4446  # The port used by sharkd
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('c: Connecting to ' + host + ':' + str(port))
s.connect((host, port))

json_string = '{"req":"load","file":"c:/traces/Contoso_01/web01/web01_00001_20161012151754.pcapng"}'
print('s: ' + json_string)
recv_json = json_send_recv(s, json_string)
print('r: ' + recv_json)

json_string = '{"req":"status"}'
print('s: ' + json_string)
rx_json = json_send_recv(s, json_string)
print('r: ' + rx_json)

print('c: Closing connection to ' + host + ':' + str(port))
s.close()

The output looks like this:

c: Connecting to 127.0.0.1:4446
s: {"req":"load","file":"c:/traces/Contoso_01/web01/web01_00001_20161012151754.pcapng"}
r: {"err":0}
s: {"req":"status"}
r: {"frames":53882,"duration":1841.532335000,"filename":"web01_00001_20161012151754.pcapng","filesize":36433896}
c: Closing connection to 127.0.0.1:4446

Acknowledgement

Writing a feature like sharkd is a big task, and so we must acknowledge the work of Jakub Zawadzki who authored the code.