Dutch KLPD Cyber Challenge - the Solution

A while ago the dutch KLPD (Korps landelijke politiediensten; the National Police Services Agency in the Netherlands) launched a cyber challenge for recruiting new skilled employees. Although I’m not living in the Netherlands and/or looking for a new job at the moment, I was a bit bored and wanted to take a look at this challenge to see what my skills were. In this blog post I’ll tell you how I did it.

Hopefully it will help you if you got stuck during the challenge, had no idea how to start or are just interested in how you could have solved this challenge.

I divided this blog post in 3 parts: 1. The easy part :P (pcap analysis) 2. A zip file with a password? Now what? (zip file analysis) 3. Android app/JAVA analysis 3.1 Part 1: Me like looking at source code. (source code analysis) 3.2 Part 2: What the hell are these messages? (crypto challenge)

Ok, here we go.

  1. The easy part – Pcap Analysis When starting the challenge you start with a pcap file (http://tweakers.net/advertorials/cybercrimechallenge). This is a file containing the raw network traffic from an network tap. A great tool for looking at this file is Wireshark. I wanted to do a quick analysis on the pcap. Because I didn’t know where I was looking for and I’m not a Wireshark guru I decided to go in a different direction. There are two tools you can use for this. For Windows you can use “Network Miner” this is a great tool if you like to take a look at what kind of data has been collected. Although this is not the tool I prefer to use for this. I’m a UNIX guy and I love the console (GUI’s are for people who want to get RSI). So an other great tool is ‘honeysnap’ (for more info about honeysnap go to https://projects.honeynet.org/honeysnap/; just remember that you have to change the IP addresses in the honeysnap config file before you are able to run a analysis).

One quick note: Because you need the IP addresses to config honeysnap you need to find all the ip addresses in the pcap. You can do this via wireshark. I did this by using a custom tool I also use for log analysis. I found the IP addresses used in the pcap file is by running my tool using the following regex:

"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"

There are probably other methods to find all the IP addresses in a file but this is how I did it ;)

After running the following command: honeysnap -c honeynet.cfg klpd.pcap (download: honeynet.cfg) you get a list of results where the following parts are the most interesting:

Analysing file: klpd.pcap

Pcap file information:
    File name: klpd.pcap
    Number of packets: 5518
    File size: 4166353 bytes
    Data size: 4078041 bytes
    Capture duration: 260.222535133 seconds
    Start time: Fri Jan 20 01:51:46 2012
    End time: Fri Jan 20 01:56:06 2012
    Data rate: 15671.3598917 bytes/s
    Data rate: 125370.879133 bits/s
    Average packet size: 739.043312794 bytes

IP packet summary for common ports:

Filter                                      Packets
Total IPv4 packets:
host 11.1.102.55 and ip                           0
host 74.50.110.120 and ip                       978
host 92.122.217.80 and ip                        27
host 203.0.113.59 and ip                        261

Total TCP packets:
host 11.1.102.55 and tcp                          0
host 74.50.110.120 and tcp                      978
host 92.122.217.80 and tcp                       27
host 203.0.113.59 and tcp                       261

Total OTHER packets
host 11.1.102.55 and not udp and not tcp and not icmp          0
host 74.50.110.120 and not udp and not tcp and not icmp          0
host 92.122.217.80 and not udp and not tcp and not icmp          0
host 203.0.113.59 and not udp and not tcp and not icmp          6

Inbound HTTP packets:
dst host 11.1.102.55 and dst port 80              0
dst host 74.50.110.120 and dst port 80          281
dst host 92.122.217.80 and dst port 80           18
dst host 203.0.113.59 and dst port 80            80

Counting incoming connections for 11.1.102.55
Counting incoming connections for 74.50.110.120
Counting incoming connections for 92.122.217.80
Counting incoming connections for 203.0.113.59

Counting outgoing connections for 11.1.102.55
Counting outgoing connections for 74.50.110.120
Counting outgoing connections for 92.122.217.80
Counting outgoing connections for 203.0.113.59

Extracting DNS data to file

Extracting all flows

Extracting from HTTP

HTTP summary for 74.50.110.120
requested_files: No files seen
20 requests served by honeypot

HTTP summary for 92.122.217.80
requested_files: No files seen
2 requests served by honeypot

HTTP summary for 203.0.113.59
requested_files: No files seen
4 requests served by honeypot

When looking closely at the results honeysnap generated you can see that there are 4 ip addresses where honeysnap created a folder for. When analyzing the data in each folder you’ll find out that the folder of “203.0.113.59” contains the most interesting data.

  1. A zip file with a password? Now what? – Zip file analysis With interesting I’m of course referring to the zip file “Off%20the%20Platter%20Source.zip.2”. When opening this file looking at the file names is not an issue and shows you that you are working with a zip file that contains the source code of an java application (an android app to be precise because you also found an “apx” file in the pcap analysis). As you probably can guess, the files contain the source code for the fictional botnet described in the challenge. Opening the zip files goes good but extracting the files is an issue because its password protected. But after a lucky guess (kuch botnet kuch) the zip file extracts and you can look at all the files. When looking at all the files you’ll find that the following path will bring you to the src of the application: “Off The Platter/src/com/botnet/offtheplatter/” *An other method for doing this is a dictionary attack. In the upcoming day’s I’ll try to release my own simple python script that takes care of this for you.

  2. Android app/JAVA analysis Now that you have the zip file content extracted and can look at the source it is time to do some analysis. Let roll:

3.1 Me like looking at source code. (source code analysis) When first looking at the source you’ll see a couple of file’s. It is a very small application and a quick analysis will show you that the application is getting its messages from a forum (http://193.200.198.84:51372/). When following the links from the source code you’ll end up at a page that requires a password. Again, in the source code this password is provided. The only thing that is done to the string that can be found in PASS (found in Forum.java) is a base64 decode. Once you decoded the string yourself (think of ‘online base64 decode’ or the lovely UNIX command “base64 -d ” where the file of course contains the base64 encrypted password) you are able to login to the forum. This is where you’ll find the encrypted messages.

3.2 Part 2: What the hell are these messages? (crypto challenge) Again we go back to the source code and we are able to see that the messages are decrypted using the following algorithm:

        @Override
        protected String doInBackground(Context... params) {
                int i, j;
                for (i = 0; i < this.messages.size(); i++) {
                        for (j = 0; j < 8; j++) {
                        Message m = this.messages.get(i);
                        m.decrypt(this.password, j);
                        //All the code from here to the END comment is completely useless.
                        //Do leave it out, it is time consuming an only generating output
                            try {
                                        Thread.sleep(250);
                                } catch (InterruptedException e) {
                                }
                            float percent = (float)(i*8+j)/(float)(this.messages.size() * 8);
                            System.out.println(percent);
                            percent = percent * 100;
                        this.publishProgress(Math.round(percent));
                        }
                        //END
                }
                //REMOVE, app specific
                this.progress.dismiss();
                return null;
                //END
        }

Below you’ll see the decrypt function that is called:

public void decrypt(String password, int bit) {
        String result = "";
        int i;

        if (password.length() == 0) {
                this.message = this.COULD_NOT_DECRYPT_NO_PASSWORD;
                return;
        }

        for (i=0; i

Basically after analysis the code you’ll see that the only interesting and real encryption part is taking place is the XOR. Also when you look at the function above you’ll see that every character is encrypted and than the stream/block cipher continues with the next char. This is (I think) a classic implementation of a XOR stream cipher. But… XOR is a very weak encryption algorithm if you know what the outcome should be (XOR is only good when the key is the same length as the message and no repetitions can be found in the message). Again, if you look at the source code you’ll see that the decryption algorithm decides if the decryption was successful if the string starts with “ENCRYPTION”. This is great! Because we now have the encrypted message and the string a decrypted message should start with. As you probably also can see all the encrypted messages start with the following pattern: “LyJwNh9iPil3”. Is it fair to assume that this is the encrypted version of the string “ENCRYPTED”? That’s right, we can assume that indeed. Ok, to come back at the weakness a XOR encryption algorithm has, XOR is a operator that is also used for data recovery. That means that you are able to lose data and recreate it with a data recovery file. The way this works is as follows: 0111 0101 – Data 1

0101 0011 – Data 2

0010 0110 – XOR between Data 1 and Data2

Now we lose Data2. We can recover this by xor’ing the data with Data1:

0111 0101 – Data 1

0010 0110 – Previously calculated XOR

0101 0011 – XOR between Data1 and XOR

Isn’t that awesome? Well, not if you are encrypting data of course because we know the result is ENCRYPTION we can exploit this vulnerability in the XOR encryption and do the following: Encrypted data: LyJwNh9iPi

Decrypted message: ENCRYPTION

Encryption key: KEY (you can find that one yourself :P)

For you who payed attention i removed ‘l3’ (the last two chars) from the pattern we found at the beginning of the string. Because it is a stream cipher and its only encrypting a single char we have to ignore these two chars to prevent getting the wrong key. It is not the same length as ENCRYPTION

Done! We now have the message we need.

Cheers, Ruben.

Comments