iHack 2019: Fun in the Wireshark World Writeup

Émilio Gonzalez
7 min readJun 20, 2019

For the iHack CTF, I built a Wireshark challenge that contained 6 flags:

You are a sysadmin in a small business. Your boss suspects that two employees exchange flags on company time. However, even though he can see slack’s private messages between employees, he didn’t see any suspicious message, but he knows that they’re communicating!

Having recently installed a network tap on the main switch of your network, you see all the packets that go through. Use the following packet capture file to uncover the 5 hidden flags (+1 bonus flag).

The track can be fully completed by using only Wireshark.

Download the pcap file.

This is a full writeup of that challenge.

Introduction: setting up Wireshark to hunt for flags

Since the goal of this challenge was to introduce people to some useful Wireshark features, I’ll show some features that I think enhances the user experience but are not needed to solve the challenge.

Changing the Wireshark layout:

Edit>Preferences>Layout, select the second layout:

It uses the screen space way more efficiently, giving more space to browse packets.

Enable IP name resolution

Edit>Preferences>Name resolution>Resolve network (IP) addresses

This helps identify the different machines on the network and lets you choose custom names for each machine.

Add destination port as a column

Edit>Preferences>Columns>+, Title “Port” and Fields “tcp.dstport or udp.dstport”

This helps making sense of the packets, as the port number often gives big hints as to what kind of data is exchanged.

Flag 1 (Uncover how the two employees communicate with each other)

The pcap contains over 67 000 packets (as shown in the bottom right of the Wireshark window):

The first step is to filter out the “garbage”. Scrolling rapidly through the packets, we see a lot of internet traffic. We can confirm this using Wireshark’s endpoint tab:

Statistics>Endpoints>IPv4, check “Name resolution”

We want to filter out this traffic. The best way to do that is to keep only the traffic where the source and the destination ip address belong to the internal network. To identify the internal network, simply choose any packet and look for the IP addresses:

The subnet 192.168.0.0/16 (with mask 255.255.0.0) is a very common subnet addresses range (another common one is 10.0.0.0/8 — with mask 255.0.0.0). Wireshark allows to filter based on subnets. We can build our filter like this:

ip.src == 192.168.0.0/16 and ip.dst == 192.168.0.0/16

With that filter, we removed almost 92% of the packets, and only 5700 are left. This is way better, but still too many.

Using Wireshark’s Protocol Hierarchy analysis feature, we see what we have left:

Statistics>Protocol Hierarchy

We see that 4000 of the 5700 packets are DNS packets. This is a lot and is worth looking at. Lets look only at DNS packet using the dns filter (don’t forget to save your previous filter using the +sign at the right of the filter bar).

Using the conversation aggregator, we can see that all the dns traffic is exchanged using the same IP address (192.168.110.2):

Statistics>Conversations, click “limit to display filter”

It’s fair to assume that this is genuine traffic. You can make sure by looking at the protocol hierarchy for this IP only (ip.addr==192.168.110.2)

So let’s filter out this address. New filter is now ip.src == 192.168.0.0/16 and ip.dst == 192.168.0.0/16 and not ip.addr == 192.168.110.2 ( ip.addr == something)is the same as ip.src == something or ip.dst == something)

We’re down to 1338 packets! From there, the rest can be analyzed manually by browsing packets, or we can see from the Conversations>TCP tab that there are odd conversations between 192.168.110.134 and 192.168.110.132:

By filtering based on port (tcp.port == 42424), we can see the desired packets. To see the content of the conversation, right click a packet, Follow>TCP stream:

"Drapeau" is the french word for "flag" and it was used so the flag could not be found by searching "flag" with CTRL+F. FLAG-e896af178e5db8c5593d33a327ae7b08.

Flag 2

The second flag was also in that TCP stream, but it wasn’t displayed correctly. The trick was to tell wireshark to display the TCP stream as UTF-8:

And the flag displays correctly! F_L__AAA_GGGGGG-👏😎👏🙈🙈🙏👀

Flag 3

According to their conversation, they downloaded some stuff over HTTP. By filtering on the ip addresses of both employees and http, we can see that 7 http requests were made:

(ip.src == 192.168.0.0/16 and ip.dst == 192.168.0.0/16 and not ip.addr == 192.168.110.2) and (ip.addr == 192.168.110.132 or ip.addr == 192.168.110.134) and http

Using Wireshark’s export HTTP objects feature, we can easily retreive all of the downloaded objects.

File>Export Objects>HTTP …

An image (something.png) was downloaded. When opening the image, there was a flag: FLAG-dc3c497d445ff873ae51fc550f5b0b5.

Flag 4

As said in the first conversation, an employee opened port 42423 for the other to connect to using TLS. By filtering on port 42423 (tcp.port==42423), we see the encrypted traffic.

The TLS connection uses TLS 1.1 and the TLS_RSA_WITH_SEED_CBC_SHA cipher suite. This cipher suite (as in many other in TLS 1.1 and 1.2) is vulnerable to future private key disclosure, which allows us to decrypt the traffic after the connection.

Note: This would not have been possible if the chosen cipher suite had the forward secrecy attribute, which all of the TLS 1.3 cipher suites have.

To decrypt the connection:

Edit>Preferences>Protocols>TLS/SSL (depending on your Wireshark version)>RSA Key list Edit>+

With that, we should see the decrypted traffic. We can see what was exchanged using the Follow TLS Stream feature:

Right click a TLS packet>Follow>TLS/SSL Stream

FLAG-72d6d56efe4f31471422a5e58881094c

Flag 5 (RDP)

The employee hints about PyRDP (an RDP man-in-the-middle) and gives two CLIENT_RANDOM data. This is the NSS key log format, and Wireshark can decrypt it. It contains the client random to identify the connection, and the bytes used to generate the symmetric key for the connection.

By simply pasting the two lines in a file, and telling the TLS dissector to use it:

Edit>Preferences>Protocols>TLS>(Pre)-Master-Secret log filename

And filtering on the RDP traffic (tcp.port == 3389), we have the decrypted traffic.

There were two ways to find the flag. The cleanest way to solve the challenge involves compiling Wireshark from source, since the RDP dissector works on the latest commit. Looking at the ClientData packet, we can see that the client requests to open the “cliprdr” virtual channel, which is for clipboard sharing:

The next packet (ServerData) contains the channelID for this channel: 1004:

We can then filter by channelID by applying a filter:

Left click an RDP packet, open protocol hierarchy until you have channelId>Right click>Apply as filter>selected

And change the channelId to 1004. This leaves 9 packets that can then be manually checked, and the flag is on the last one:

FLAG-06c078dd3ebf7801575feaa109f73ddc.

The other way was to follow the TLS stream, show the data as UTF-16 (since it’s how RDP handles most of its strings) and search for “FLAG”:

Bonus Flag (ARP spoofing)

A computer did a brief attempt at performing a man-in-the-middle attack on the whole network. Find the mac address of the attacker as well as the packet number that prove such attack. Flag format: macAddressLowercase-packetNumber

Wireshark allows to find ARP spoofing attempts when it detects that two different MAC addresses say belong to a certain IP. Using this filter: arp.duplicate-address-detected, we find our culprit:

000c29de1219–58544.

I hope you learned something about Wireshark or anything else that I put in this challenge! Constructive feedback is welcome :)

--

--

Émilio Gonzalez

Blue team analyst in Quebec, Canada. Passionate about cybersecurity and urbanism. Twitter: @res260 https://twitter.com/res260