In this section

0.3 The Toolset and Its Versions

Module 0

Introduction

The course uses a small set of tools, all of them free and open source, and every lesson names the version it was written against. This lesson introduces each tool, says why the course uses it and which version, and explains why the version matters as much as the tool.

The set is deliberately small. An investigator who knows six tools well can answer most questions network evidence can answer; one who knows twenty tools slightly answers fewer. Each tool here does one job in the chain from a packet on the wire to a finding in a report:

The toolset as a chaintcpdumpcaptures packetscapture filespcap, kept asevidenceTShark, Zeek,Suricataread and log themlogsconn, dns, ssl,eve.jsonjq, Pythonfilter andcorrelateone chain: what is captured, what the tools write from it, and what you ask of what they wrote

The course's tools in the order evidence passes through them. Each one's output is the next one's input.

tcpdump captures. TShark and Wireshark read captures packet by packet. Zeek turns captures into logs of connections and protocol events. Suricata matches captures against rules and writes alerts. And jq and Python filter and join what the others wrote. The rest of the lesson takes them in that order, then shows how to check every version at once.

All six run on Linux, and all but tcpdump's capture run equally well on macOS and on Windows through the Windows Subsystem for Linux, which lesson 0.4 covers. None needs a server, a license or an account. The course's investigations need a laptop with a few gigabytes free, the lab pack and these tools, and nothing else.

The course does not use a SIEM or a commercial analysis platform. That is a choice, not a limitation: the tools here are what those platforms are built on or modeled after, and an analyst who can answer a question with Zeek's logs and jq can answer it in any query language once they learn its syntax. The reverse is less often true.

1

Why Versions Matter

Output is a property of the version

A tool's output depends on its version. Between releases, a log gains or loses a field, a protocol parser handles a case differently, a default setting changes, or a command-line option is renamed.

Most changes are small, and most do not matter to a given question. But an investigation that relies on a field that a newer version renamed, or a rule keyword that an older version does not understand, can go wrong in ways that are hard to see.

Two ways to name a tool

By versionThe course
Outputreproducible
A differencetraceable
A changenoticed
By name onlyAvoid
Outputwhatever is installed
A differencea mystery
A changesilent

The course handles this by naming versions everywhere. Every lesson that relies on a tool's behavior ends with a line naming the version that produced its output, and the build process checked each tool's version before writing any lesson. When your output differs from a lesson's, the version line is the first thing to compare.

This is also good practice beyond the course. An investigation report that cites a Zeek log should be able to say which Zeek version wrote it, because a reviewer reproducing the finding years later needs to know.

The same is true of a detection: a rule written for one Suricata version may not load, or may match differently, on another. Recording versions is part of making findings reproducible, which is the first of the capstone's assessment criteria. Every answer guide in the course names the versions its outputs came from for the same reason.

None of this means you must match every version exactly to take the course. Lesson 0.4 shows how to install the versions the course uses where that is practical, and what to expect where it is not. The rule is simply to know which version you are running, and to suspect it first when an output surprises you.

A concrete example shows why. Zeek's conn.log has a field recording the connection's state, a short code such as SF for a connection that set up and closed normally.

The codes are stable, but other fields come and go between releases, and a command that selects a field by name prints nothing for a field that does not exist in the log you have. An analyst who does not know their version reads that silence as a finding. One who does checks the log's header, sees the field is missing, and knows why.

2

tcpdump

Capture

tcpdump captures packets from a network interface and writes them to a file. It is the oldest of the course's tools and the most widely available: it is packaged for every major Linux distribution, included with macOS, and found on many network appliances. The course's captures were taken with it:

$ tcpdump --version | head -1
tcpdump version 4.99.4

The course uses tcpdump for capture rather than analysis. Its strength is that it is small, reliable and scriptable, and that its capture filter language is the same one Wireshark and most other tools use for capture.

Module 2 teaches capture properly: where a capture point sits, what a filter excludes, how a snap length truncates packets, how a ring of files overwrites the oldest, and how to tell from a capture file whether it is complete. Every one of those decisions is made when tcpdump starts, and none can be undone afterward, which is why the course teaches them before any analysis.

You will mostly read tcpdump's output rather than run it, because the lab pack's captures are already taken. Lab Setup in Phase 0 shows you how to capture your own, from a small lab on your own machine.

The version above is the one the course's lab used. tcpdump changes slowly, and for the capture work the course teaches, recent versions behave the same; The course's captures are in the classic pcap format, which every tool here reads.

One caution belongs here because it comes up in Module 2. tcpdump prints a count of packets dropped by the kernel when it stops, and that count is one of the few records of a capture's completeness. The lab pack keeps those counts beside each capture, in the stats files, and lessons read them.

tcpdump also matters for what it cannot do. It writes what crossed the interface it was listening on, at the moment it was listening, and nothing else. It has no idea whether that interface was the right place to listen, whether the network sent it every packet, or whether its clock was right.

Those questions are the subject of Module 2, and they are the first ones to ask of any capture you are handed.

3

Wireshark and TShark

Reading captures packet by packet

Wireshark is the graphical packet analyzer, and TShark is the same engine at the command line. The course uses TShark in its lessons, because a command and its output can be shown exactly, and Wireshark when a lesson needs you to look at a packet's structure. Both come from the same release:

$ tshark --version | head -1
capinfos --version | head -1
TShark (Wireshark) 4.6.9 (v4.6.9-0-g2d548b197c75).
Capinfos (Wireshark) 4.6.9 (v4.6.9-0-g2d548b197c75).

The course was written against Wireshark 4.6.9, the current stable release on Wireshark's download page. capinfos, which you met in lesson 0.2, is part of the same release and summarizes a capture file: its packets, its time span and its data rate.

TShark's display filter language is the most used piece of syntax in the course. It selects packets by any field the dissectors understand, such as an address, a port, a TLS server name or an HTTP status, and it is the same in Wireshark and TShark. Module 3 teaches it properly, along with following streams, reassembling sessions and extracting files.

Wireshark's dissectors are also the course's reference for what a protocol looks like. Where a lesson says a field means something, it is the field as Wireshark 4.6.9 decodes it, and where Wireshark warns about something, such as a missing segment or a malformed packet, the lesson reads the warning rather than ignoring it.

The course uses TShark rather than Wireshark in its lessons for a practical reason as well as a teaching one. A command can be copied, run and compared; a sequence of clicks in a window cannot be shown exactly or repeated reliably. Where a lesson does use Wireshark, it says which menu and which pane, and the same result is always available from TShark too.

If you prefer the graphical tool, use it alongside the commands. Opening a capture in Wireshark while you work through a lesson's TShark commands is a good way to connect the two views: the command's output on one side, the packet's structure on the other. Module 3 does exactly that for the first sessions it reconstructs.

4

Zeek

Captures into logs

Zeek reads traffic and writes logs about it: one line per connection in conn.log, one per DNS query in dns.log, one per TLS handshake in ssl.log, one per HTTP request in http.log, and many more. Those logs are what most network investigations actually search, because they are far smaller than captures and keep their key facts long after the captures are gone. The course uses Zeek's long-term-support line:

$ zeek --version
/opt/zeek/bin/zeek version 9.0.1

Zeek publishes two kinds of release: a feature line, which moves quickly, and long-term-support lines, which receive fixes for longer without changing behavior. The course uses the long-term-support release so the logs it teaches stay stable. Zeek's installation documentation describes both kinds of package and the Docker images built for each.

Module 4 teaches Zeek's logs in depth: what each field records, how a connection's uid joins one log to another, and what Zeek writes when it cannot parse something. From then on, almost every investigation in the course reads Zeek's logs, and the commands use zeek-cut, a small tool that ships with Zeek and prints chosen fields from a log by name.

You will also run Zeek yourself, from lesson 0.5 onward, on the captures in the pack. Running it on a capture writes the same logs the pack holds, which is a useful check that your installation behaves like the course's.

Zeek's logs have a property worth knowing from the start: they summarize. A connection's conn.log line records its endpoints, its duration, its bytes and its state, but not its content. A DNS query's line records the name and the answer, but not why the client asked.

That makes the logs fast to search and cheap to keep, and it means every finding that rests on them is a finding about what was summarized. When a question needs the content, the investigation goes back to the capture, if the capture still exists.

Zeek is also extensible, with its own scripting language, and Module 11 uses two short Zeek scripts the course provides to compute measures Zeek does not log by default. The lessons explain each line; you do not need to learn the language to follow them.

5

Suricata

Rules and alerts

Suricata reads traffic and matches it against rules, writing an alert when a rule matches and a structured log of protocol events in a file called eve.json. The course uses it for signature detection: reading what an alert claims, testing it against the traffic, and writing better rules. The version is the current release of the supported branch:

$ suricata -V
This is Suricata version 8.0.8 RELEASE

Suricata's maintainers publish an end-of-life policy: each branch is supported for three years from its first stable release, and a new major branch arrives every two years, so the two overlap for a year. The 7.0 branch reached its end of life on 7 July 2026, which is why the course uses the 8.0 branch rather than the 7.0 releases some Linux distributions still package:

Suricata's release lines2023202420252026202720282029Suricata 7end of life Jul 2026Suricata 8current; supported to about 2028three years of support per branch, a new branch every two: the overlap is the year to upgrade in

Drawn from OISF's published policy and the 7.0 end-of-life date. Start dates are the policy's three years counted back; branch 8's end date is the policy applied, not an announced date.

Branch matters for Suricata more than for most tools, because rule syntax and keyword behavior change between major versions. A rule the course writes in Module 11 or 14 is written for 8.0 and tested on it; the lessons say where a keyword's behavior is specific to the branch. Module 4 introduces Suricata's alerts and eve.json, Module 11 teaches rule writing, and the capstone begins with a Suricata alert.

The course runs Suricata against capture files rather than live traffic, so it does not need Suricata's full sensor configuration. A rules file, a capture and a few command-line options are enough, and the lessons show exactly which. That keeps the setup small enough to repeat on any machine, and the same commands work on the benign and malicious windows alike.

Suricata and Zeek overlap, and the course uses both deliberately. Zeek describes everything it sees; Suricata flags what matches a rule. An investigation usually starts from a Suricata alert and proceeds through Zeek's logs, as the capstone does, and a detection may be written for either, depending on whether the thing to catch is a pattern of bytes or a pattern of behavior. Module 11 teaches when to choose which.

Suricata also writes protocol logs of its own in eve.json, alongside its alerts, and they record some things Zeek's logs do not, and the other way round. The course mostly uses Zeek's protocol logs and Suricata's alerts, and says so when it uses Suricata's protocol records.

6

jq and Python

Filtering and correlating

The last two tools work on what the others wrote. jq filters and reshapes JSON, which is the format of Suricata's eve.json, the endpoint events in the later modules and the domain controller's audit records. Python is used for the short scripts the course provides, which do things a one-line command cannot: measure the intervals between connections, merge every source into one timeline, or score a detection against two windows:

$ jq --version
python3 --version
jq-1.7
Python 3.13.18

You do not need to write Python to take the course. The scripts are in the lab pack, each one documented at its top and explained in the lesson that first uses it. Reading them is worthwhile, because each is short and does one thing, and knowing what a script does is part of trusting its output. Here are some of them:

The course's scripts in the lab pack

01cloudflow.pyPython, explained where it is used
02intervals.pyPython, explained where it is used
03lookalike.pyPython, explained where it is used
04ndrecord.pyPython, explained where it is used
05ndrule.pyPython, explained where it is used
06ndscore.pyPython, explained where it is used
07parts.pyPython, explained where it is used
08path.pyPython, explained where it is used

jq, on the other hand, you will write, a little at a time. The lessons introduce its syntax as they need it: selecting records, choosing fields, counting and grouping. By the later modules you will be reading jq expressions of a few lines without effort. The ones the course uses most are collected in the jq section of the Phase 0 cheatsheets, with the record each one expects.

Release lines the course chose

Wireshark 4.6

The current stable branch

Zeek 9.0

The current long-term-support line

Suricata 8.0

The supported branch since Suricata 7 ended

tcpdump 4.99

The release the lab captured with

The course chose each release line for a reason: the current stable or long-term-support line in each case, so that what you learn stays valid for as long as possible and the tools are supported while you use them.

Python also matters for a reason beyond the scripts.

Many of the course's commands are one-line Python programs, written inline when a calculation is too fiddly for awk but too small for a file: the offset between two clocks, the span of a set of times, a join between two logs on a shared key. They are shown in full, and they use only Python's standard library, so any recent Python 3 runs them.

jq and Python are also the tools you are most likely to use on evidence outside the course: a cloud provider's logs, an EDR export, a SIEM's search results downloaded as JSON. The habits the course builds with them transfer directly.

7

Checking Every Version at Once

The command to keep

Before you start Module 1, and whenever an output surprises you, check the versions you are running. One loop prints the first version line from each tool:

$ for t in 'tcpdump --version' 'tshark --version' 'zeek --version' \
  'suricata -V' 'jq --version' 'python3 --version'; do
  $t 2>&1 | grep -m1 -E '[0-9]+\.[0-9]+'; done
tcpdump version 4.99.4
TShark (Wireshark) 4.6.9 (v4.6.9-0-g2d548b197c75).
/opt/zeek/bin/zeek version 9.0.1
This is Suricata version 8.0.8 RELEASE
jq-1.7
Python 3.13.18

That is the course's toolset, at the versions every lesson used. Lesson 0.4 shows you how to install them; when you have, run the same loop on your own machine and compare. Where a tool reports the same version, your outputs should match the lessons'. Where it reports a different one, expect small differences and read the version line at the foot of any lesson whose output differs.

The reasonable mistake

Assuming the latest version is the same as the course's

The analyst installs whatever the package manager offers, sees a field missing from a Zeek log or a rule that will not load, and concludes the lesson is wrong.

Instead: Check the version first. Lesson 0.4 shows how to get the versions the course uses, and the version line at the foot of each lesson says which one produced its output. A different version is a reason to expect differences, not a reason to distrust either.

Two of the tools need particular attention when you check. TShark from your distribution's own packages may be an older branch than the course's, and the difference shows in some protocol fields. And Suricata from a distribution may still be on the 7.0 branch, which has reached its end of life and handles some rule keywords differently. Lesson 0.4 shows how to get the current releases of both.

Keep the loop, because versions drift: package managers upgrade tools quietly, and a machine that matched the course last month may not match it now.

Put it in a small script on your machine, or keep this lesson open, and run it whenever you install a tool, upgrade one, or move to a different machine. It is a small habit that saves a lot of confusion, and it is the same habit a careful investigator applies to every tool whose output goes into a report.

The loop prints only the first line that contains a version number, which is the version line for each of these tools. If a tool is not installed, the loop prints an error for it instead, which is itself useful: it is a list of what lesson 0.4 still needs to install.

Notice the form of each tool's answer. Zeek prints the path of the program it ran, which tells you which installation answered if you have more than one. TShark prints its build information in brackets. Suricata adds a word saying whether it is a release build. Each is worth recording as printed, because it is what you would quote in a report.

Do

Practice

Know your tools
your own machine
Do this Check what you already have
  1. Look for each tool. Run each version command on your machine, if the tool is installed.
  2. Compare. Note which tools match the course's versions and which differ or are missing.
  3. Note the branches. Wireshark 4.6, Zeek 9.0 long-term support, Suricata 8.0.
  4. Plan the installs. Mark what lesson 0.4 needs to install or upgrade.
You will have a list of the tools to install or upgrade before Module 1.

Versions this lesson relies on: Wireshark and TShark 4.6.9; Zeek 9.0.1 (LTS); Suricata 8.0.8; tcpdump 4.99.4.