ASIS CTF Finals 2015 – Giloph (crypto 300)

October 13, 2015

In this challenge we were given a normal network capture file of some “TCP” traffic.


After carefully looking at the capture you can guess that it is not actually just TCP traffic but rather TLS traffic. Fix that in wireshark by right-clicking on a packet and choose to “decode as… > ssl”
(That step actually took way more time for me than it should have, I searched for the string “http/1.1 spdy/3.1h2-14h2uP” in packet #4 and found some other captures online that were about TLS traffic so I figured that must be it, but there are many ways to see or guess the traffic type…)

Now we can see this challenge is about TLSv1.2. We have to think about ways to decrypt the traffic. First I looked at the certificate but nothing seemed to be “attackable” there (like a weak modulus, this one was 1024bits). Also the CipherSuite of the conversation was “TLS_DHE_RSA_WITH_AES_128_CBC_SHA” which means a private key wouldn’t actually be very helpful since the “DHE” part provides forward secrecy.
At least in theory. So how can we break the encryption? The RSA part is not attackable – Let’s take a look at the DHE (Diffie-Hellman) part:

Observe packet #6, the ServerKeyExchange part of the packet


We can actually see the parameters of the Diffie-Hellman Key-Exchange, which is normal. The abnormal part of the exchange are the values of the parameters. A quick look at wikipedia reveals:
“The protocol is considered secure against eavesdroppers if G and g are chosen properly.”

I’m not a math person and to be honest I had no idea what “chosen properly” means but went ahead and looked at the attack mentioned in the next sentences, since I assumed those parameters were not “proper”.

After studying that, it seems that the key exchange is attackable if (p-1) can be factored into “small numbers”. I was not sure what exactly that means, but I tried to factor (p-1) with my favourite algorithm I copied from stackexchange and it turns out it has quite a lot of small factors!

[2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 17, 17, 37, 37, 37, 37, 37, 37, 43, 43, 43, 43, 43, 43, 43, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 67, 67, 67, 67, 67, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 83, 83, 83, 83, 103, 103, 107, 107, 107, 107, 107, 109, 109, 109, 109, 109, 109, 127, 127, 127, 127, 127, 127, 127, 163, 167, 167, 167, 167, 167, 179, 179, 179, 179, 179, 197, 197, 197, 197, 197, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199L]

Okay, now we know there is a Diffie-Hellman Key-Exchange with some bad numbers and there exists some algorithm to break it. We could try to implement it, or just search for someone else who did it. I found this website:

And indeed: It takes less than a second for it to return the (secret!) exponents. If you want to understand what happened there, go through my code, I tried to explain it in the comments there a bit. If you know how Diffie-Hellman works and get what this attack does already, you can skip it.

Thanks Java for this BigInteger number, it’s our secret!


Feels good to break an algorithm that is used millions of times everyday… but now what. We have a big number but we still can’t see what’s in those packets. It’s time to dig into the RFCs about TLS:

Take a look at “8. Cryptographic Computations” and the points below it. That seems relevant! We find out that:
“The negotiated key (Z) is used as the pre_master_secret, and is converted into the master_secret, as specified above.”

Okay, now we know what that big number is and roughly what to do with it. It’s our “Pre-Master-Secret” and we need to somehow derive the “Master-Secret” (which is used to derive even more stuff). A teammate luckily found this tutorial, which shows you how to precicely do what we need:

After filling the script with the right numbers (client/server-secret from the pcap) we arrive at the following:


which gives us… The “MASTER-SECRET”:


Another number, WOW!

At this point I tried feeding the values we have to wireshark, for some reason it didn’t decode the packets though. This is supposed to work:
if you give it the CLIENT_RANDOM (used in computation above) and the Master-Secret.

So we tried a solution without wireshark: we followed the tutorial above further and wrote this script (or rather copied and filled in the right numbers) to derive the symmetric keys:

 clientkey 872f0e68167f5201bbc661417f148421
 clientiv  4eaaf3d612cb2629767aa11e1601a7ef
 serverkey 73eb5d0236c76e957381ff269081fba4
 serveriv  1dac9c3db71249572009791f82b5e87b

Now we have symetrically encrypted ciphertexts (ApllicationData in the pcap) and symmetric keys/ivs! Let’s try to decrypt it:

Just put the ciphertext (hex) into it, choose AES-CBC and give it the client/server “write key” and iv from the script (depending on if you want to decrypt the data coming from or going to the server/client).


(source .dat files in zip. link at the top)

We can see a GET-request and some answer, almost done!
Last step is to uncompress the gzip from the GET-response. I just used “binwalk -e” (overkill but it worked) on the .dat file and got the HTML-response:

<html><head><title>Top Secret</title></head>
<body><h1>Flag is ASIS{f702d759801533096be29291fd6e82c3}</h1></body></html>

Now that’s quite a topsecret website, and a flag too!
This was one of the most interesting challenges I solved in quite a while! It was very interesting to find out about so many of the internals of TLS and actually calculating all relevant keys “by hand”. Think about it: all of those calculations (and more) are done every time (close enough) you open a website that uses HTTPS!

Thanks ASIS!

Leave a Reply