Orcish - Swamp CTF 2018

The full solution of Orcish challenge from Swamp CTF 2018.


  • ICMP data bytes exfiltration from pcap

Challenge Description

An army of orcs was spotted not too far from town. We were listening in on some of their communications but we have not been able to find anything containing their battle plans. Maybe they are disguising the messages somehow…

Challenge file: data.pcap

Initial analysis

We are provided with a network packet capture (.pcap) file. Loading into Wireshark, and checking the protocol hierarchy we see some common protocols stand out.


  • UDP
  • TCP
  • HTTP
  • ICMP

For the sake of making this post precise, I won’t be delving too much into the unnecessary parts. If you are interested to know, please drop comments or feel free to contact me.

Analysis of ICMP streams

Using the ICMP filter in Wireshark, as soon as we see the first ICMP packets, we see that the Info column shows some as Obsolete or Malformed?. This error here is of particular interest to us.


We see that the error corresponds to the ICMP Type field. The Type field corresponds to determining what type of ICMP packet it is. E.g: ping-reply, ping-request, reserved etc…

Since we see that in the current case, it is malformed, that must mean the type field here has been configured manually or intentionally. So, that is the lead.

Let us see what data we can gather from the first few malformed packets.

Analysis of Packet number: 6971-6976


ICMP Type: 71 –> ‘G’ (In ASCII)


ICMP Type: 73 –> ‘I’ (In ASCII)


ICMP Type: 70 –> ‘F’ (In ASCII)


ICMP Type: 56 –> ‘8’ (In ASCII)


ICMP Type: 57 –> ‘9’ (In ASCII)


ICMP Type: 97 –> ‘a’ (In ASCII)

So far, if we concatenate the collected types, we get GIF89a. This indicates the file signature of a GIF image.

Writing script using scapy

So in order to ease our job, let us write the script to exfiltrate all the required data using scapy.

from scapy.all import *

r = rdpcap("data.pcap")
list_type_bytes = [] #list to store all type bytes

for i in range(len(r)):
    if r[i].haslayer(ICMP) and r[i][IP].dst == '': # filter to check destination IP and ICMP layer.
        type_byte = chr(r[6970][ICMP].type)

concatenate = ''.join(list_type_bytes) # join all the list elements to form single string stream.

f = open('flag.gif','w')


So, let us open the file flag.gif


Flag: flag{we_ride_at_midnight}