CSE Puzzle Challenge - Puzzle 16 - Solution

Notes:

From the challenge description we can gather 2 key pieces of information.

  1. Alkria and Lı́onra are only supposed to be communicating between the hours of 4-5 am. Thus any communication between the two AI out side of this time frame is suspect and should be evaluated.
  2. There is a fear that the AI have developed their own language. Thus we should expect that there communications may be encoded in some way.

The Pcap

Looking at the pcap we can gather some basic understanding of the communications network within the Cyber Dyner.

1. Method of communication is XMPP, it appears they are using a jabber server for communication within the restraint.

2. There appear to be 5 entities communicating: (Use a Wireshark filter of “XMPP.presence” to easily see all the clients that logged on in the PCAP.)

IP Addr Client
10.10.10.10 kitchen@cyberdyner.chat
10.10.10.66 busboy@cyberdyner.chat
10.10.10.99 hostess@cyberdyner.chat
10.10.10.68 alkria@cyberdyner.chat
10.10.10.17 Lionra@cyberdyner.chat
10.10.10.01 XMPP server

3. Isolating for different stream types we can see that Alkira sends an SI stanza to Lı́onra, offering a file transfer of mime-type “application/zip” with the name “SecretPlan.zip”. This negotiation can be isolated by using "XMPP.si" as the expression in the wireshark filter. From these 4 packets we can gather the following information:

  1. Alkira is sending a file to Lı́onra.
  2. mime-type: application/zip
  3. name: SecretPlan.zip
  4. size: 35871
  5. negotiated transfer method: IBB stream

4. The IBB stream can then be isolated further by using XMPP.ibb as the Wireshark expression filter. This results in the full traffic of the data transfer. Since we have already determined the name, type and size of the file and with a brief investigation of the transfer packets we can see that there were no duplicate packets sent. Thus, these packets can be further filtered to just the packets containing file data. To do this use XMPP.ibb.data as the expression filter in Wireshark. The filtered results contain 18 packets, though if you look at the source and destination IP addresses you can see that Alkira sends the data to the XMPP server and the XMPP server sends the data to Lı́onra. This means we have two copies of the file within the 18 IBB-DATA packets, we can isolate this even further by adding an ip.dest filter to our Wireshark expression as follows:

XMPP.ibb.data && ip.dst == 10.10.10.17

This leaves us with 9 packets over which a secret file is sent. If you are seeing packets labeled “UNKNOWNPACKET”, right-click on a packet in the stream and select “Protocol Prefrences” and make sure the “Reassemble XMPP messages” box is checked.

Isolating Conversation Between Alkira and Lı́onra

Since we now know what we are dealing with isolating the conversations becomes a lot easier. To isolate the messages sent from Alkira to Lı́onra we can use the following Wireshark expression to isolate the full conversation between the two AI.

(XMPP.from == "alkira@cyberdyner.chat/73984829149751418001922" &&
 XMPP.to =="Lionra@cyberdyner.chat/25821029832568330391858") ||
  ( XMPP.to == "alkira@cyberdyner.chat/73984829149751418001922" &&
    XMPP.from =="Lionra@cyberdyner.chat/25821029832568330391858" )

If we take a look at these isolated packets we can get an idea of what Alkira and Lı́onra are saying to each other, it seems to come in one of the following three formats (and then followed by a file transfer):

  1. "Bonjour": Both servers say hello to each other once, pretty early in the pcap.
  2. “Coutellerie requise à ces tables: . . . ”: This format happens a lot, and is followed by a list of 3 rows of table numbers.
  3. “Condiments requis à ces tables: . . . ”: This format is rare but it is also followed by 2-3 rows of table numbers.

Evaluating the Communication Sequences for Patterns

If we assume the “Hello” message to be a simple courtesy message (as all clients share a “Hello” message) we can rule it out of the secret messaging communications. The remaining XMPP ‘message’ communications at very least share the following similarities:

  1. Lı́onra is the first to send a cryptic message.
  2. Lı́onra sends 14 messages to Alkira before Alkira responds.
  3. The last message Lı́onra sends before Alkira responds uses the wording “Condiments required at tables: . . . ”, all other messages before this refer to “Cutlery”.
  4. Alkira then responds with 16 messages before Lı́onra replies.
  5. The last message sent by Alkira before Lı́onra replies, talks of “Condiments” while the 15 messages that proceeded it spoke of “Cutlery”.
  6. 19 final messages are sent from Lı́onra to Alkira, before Alkira replies, again ending in a message about “Condements”, where all previous were about “Cutlery”.
  7. 11 final messages are sent from Alkira to Lı́onra, again ending in a message about “Condements”, where all previous were about “Cutlery”.
  8. 23 packets later Alkira initializes a file transfer request with Lı́onra.

From these observations, it would be safe to assume that the switch from cutlery to condiments indicates an end of message (EOM). Thus Lı́onra’s first 14 messages could be though of as one message fragmented into 14 sections. In each of these 14 messages other than the EOM marker, the only things that changes are the table numbers.

Taking a closer look at Table Numbers

To do this we are going to start with the first 4 fragments Lı́onra’s first message, packet No 341, 372, 401 and 430.

Packet No and Tables Mentioned
Packet No Tables Mentioned -
355 0x05, 0x06, 0x01, 0x02
0x07, 0x0C, 0x0B, 0x0A
0x0E, 0x13, 0x12, 0x11, 0x10, 0x14
From this sample we can observe/hypothesize the following:
390 0x00, 0x05, 0x06, 0x02, 0x03
0x07, 0x08, 0x0D, 0x0B, 0x0A
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
Table numbers in the first row are limited to the range 0x00 - 0x06 inclusively.
421 0x00, 0x05, 0x04, 0x03, 0x02, 0x06
0x07, 0x0C, 0x0D, 0x0B, 0x08, 0x09
0x0E, 0x13, 0x12, 0x11, 0x10, 0x14
Table numbers in the first row are limited to the range 0x07 - 0x0d inclusively.
447 0x00, 0x05, 0x06, 0x04
0x07, 0x08, 0x09
0x0E, 0x13, 0x14, 0x10, 0x11
Table numbers in the first row are limited to the range 0x0e - 0x14 inclusively.

 

If we take a closer look at the layout of the restaurant we can find all of the tables in these ranges within 3 large table groupings. Each row in the message seems to correspond to one of the 3 table groupings. Such that, the first line of the message corresponds to the first table group, the second line in the message to the second table group and likewise, the third line in the message to the third table group. Figure 2 below, shows the tables as well as what highlighting the mentioned tables in packet No. 355 would look like.

Figure 1: Highlighting Tables Mentioned Message

It appears that Alkira and Lı́onra are using tables 0x00 - 0x14 as 3 seven segment displays. Given the display limitations of 7-segment displays it is not likely that Alkira and Lı́onra are writing in plain text on these displays.

Extracting the Messages

If you applied the Wireshark filter from “Isolating Conversation Between Alkira and Lı́onra” then you can simply right-click any packet and select “Follow->TCP” from the context menu (otherwise you will need to first find a packet sent to or from either AI). This will cause Wireshark to extract all XMPP data from all packets between the XMPP server and the client and display it in a new window. At this point if you did want to select just one side of the conversation, it can be achieved by selecting the desired packet flow direction from the drop-down menu highlighted in blue in Figure 3.

Figure 2: Wireshark Further Filtering Streams by Sender/Receiver

1. Select Save as...

2. Save the file with a “.xml” extension.

Since all the XMPP packet data is in XML we will need to create a script parse the XML recovered from the TCP stream.

Prepping the Raw XMPP Data

After opening the newly created XML file in a source code editor (such as Sublime or Notepad++) we can see the raw XML is in a minified state and not overly easy to edit. If we do a “Find all” on ’><’ we can in one step create cursors at all these locations and implement a new line between the two carrots. This will at least give us a more comprehensive view of the XML file (see Figure 4). To parse this XML file simply, it’s easier if we get rid of open tags that do not have closing tags and put all the raw data under one root tag.

Figure 3: Raw XMPP Packet Dump

To accomplish this we removed all the initial login authorization and presence packets (lines 1-42 inclusive), stopping at the first tag. Then surround the entire xml data with root tag we labeled (See accompanying file AI.xml or AI_fr.xml).

Rebuilding and Decoding the Secret Messages

This section is broken down into two sections: Rebuilding, which covers the extraction and reassembly of the file transferred over the IBB stream; Decoding, which covers the extraction and decoding of the secret messages shared between Lı́onra and Alkira. The Rebuild and Decode functionality are eventually compressed into a single script that will do all the heavy lifting for us (See CD_solution.py for the complete solution).

Rebuilding

To extract just the data from the IBB stream we need to restrict our search through the XML file to < iq > tags. Before a file transfer can begin there is a negotiation that occurs between the two parties to agree on the transfer method. It is in this exchange that we can retrieve the name of the file. Once the method of transfer is set to IBB we need to focus our search to tags with a < data > child. Taking this one step further, if you take a look at the actual data in the < data > tags you may notice that it is encoded. This encoding appears to have an alphabet of [A-Za-z0-9+/=]. Thus, a likely assumption of the data’s encoding method is base64. A little research on the In-Band-Bytestreams (IBB) XMPP protocol (XEP-0047) will quickly confirm this assumption. The following function executes the extract and rebuilding the transferred file from the extracted XMPP packets in accordance with the information outlined above.

Extracting and rebuilding the transferred file is not enough. When we attempt to unarchive the file we are asked for a password.

Decoding

To extract the all the actual text from messages between Alkira and Lı́onra we will need to filter out all the useless chatter and isolate just the messages that are sent to Alkira from Lı́onra or to Lı́onra from Alkira. The following script does this and stores the messages in a separate file.

This will create a file called “serverChat.txt” that will look like the output seen in Figure 5. If we think of the

first grouping of tables as a 7-“Table” display, we can map the tables values mentioned by Alkeria and Lı́onra to their hex representation as follows:

With this map we can map all the 7-“Table” displays by reducing there Table Id number by their display index (0, 1, 2) multiplied by 0x07. Such that the first 7-“table” display would be at an index of 0 and the last at an index of 2. Given that each 7-“table” display is referred to on a new line in the message body the distinction should not be difficult. The following code is one example of how the decoding may be accomplished.

It is possible to verify whether a “5” is always encoded the same way in a 7-“Table” display, or determine all possible permutations of the table Id’s to display a “5”. However, we decided to go another route. The above function uses the number of tables in the 7-“Table” display not mentioned as an index into a dictionary, which then uses the summation of the table Id’s mentioned to determine the value that would be displayed.

As you can see with this method of distinction we end up with 2 clashes in the 2 nd index. Thus, we check for these 2 clashes first otherwise we can retrieve the display value from the list of dictionaries called “value”. Though there is an added effort to avoid clashes this method determines the display value regardless of the order the tables are mentioned. Furthermore, a quick glance at the for loop in this function demonstrates how the display index is used to adjust table Id’s such that all displays can be evaluated as if they were the first display.

Putting it all Together

Note: The full decode and rebuild code can be found in CD_solution.py.

In the end we discover Alkira and Lı́onra secret conversation went as follows:

Lionra@cyberdyner.chat: Tonight we take over.
Alkira@cyberdyner.chat: I have the perfect plan.
Lionra@cyberdyner.chat: After this, it will be ours!
Alkira@cyberdyner.chat: PW: SWEETREVENGE

Using the password to archive the SecretPlans.zip we discover that after all the time, energy and money Cyber Dyner Systems put into training Alkira and Lı́onra to be the best waitstaff they could be, the two AI went rogue desperately trying to become bakers. That said, if you try out their recipe you will see, they truly had a gift for it!

 

Enjoy solving puzzles? Make a career out of it!