Crypto challenges - WOWHacker CTF

Last week team CLGT took part in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WOWHacker CTF. I was in charged of crypto challenges, so I decide to write something about challenge 1 and challenge 10.

1. Challenge 1

Challenge 1 is...crazy hahaha. Only one or two teams could solve it until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 author (hello hinehong :-D) gave out a list of 7 hints. I have designed some web-related crypto challenges (which you will see soon ^^) so I think cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 difficulty of challenge 1 relies on how fast people can guess cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 meaning of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cookie. It would be easier for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 teams if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 author sets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cookie as cookie = cipher + "|" + key. BTW, here's my solution.

When you access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 link above, you'll see a bunch of javascripts. After decoding those javascripts (which I leave as exercise for readers), you'll see a form whose target is http://221.143.48.96:8080/you_are_cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365_man_but_try_again.jsp. This form accepts a parameter named "hong" which is eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r true or false. If you set hong=true, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server sends back a cookie like below:

id =pKCdQgyJb4dziUESVUv+5qBIoGwQgL2WB@ae506e

This looks like a base64 encoded string, but it's not. In fact you need to modify it a little bit before you can base64 decode it. This is, as I said previously, why this challenge is hard.

One trick I learn from this challenge is to guess cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 boundary between key and cipher text, one should try to truncate one character a time and base64 decode cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string until he gets an output whose length in bytes is a multiple of 8 or 16, which are common block cipher's block length.

The cookie can be eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r "cipher + key" or "key + cipher", so one should try cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 above process in both cases. If you can't find any such output, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n you know your cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ory is wrong, i.e. cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cookie is in some ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r form. Fortunately, my cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ory is right in this case.

It turns out that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first 32 bytes of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cookie is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cipher text, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest 8 bytes is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key. It's a 8-bytes key, so this cookie should be encrypted by DES which is a popular 8-bytes key block cipher. I wrote a small python script to decrypt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 it:

>>>from Crypto.Cipher import DES
>>>cookie = 'pKCdQgyJb4dziUESVUv+5qBIoGwQgL2WB@ae506e'
>>> key = cookie[32:]
>>> data = base64.b64decode(cookie[0:32])
>>> des = DES.new(key, DES.MODE_CBC)
>>> des.decrypt(data)
'wowhacke\xd6\xe0\xbc*e\xe7\n\xc7\x1a\xf92w6H\xfd\xe5'

Hmm. I remembered I tried to submit 'wowhacke' to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 scoring server, but, of course, it's not cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct answer. Then I wasted cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next hour to test various stupid cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ories to understand what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last 16 bytes of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 output are.

It was not until I nearly gave up on this challenge, I realized cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 obvious: this is mode ECB stupid!!! Why on earth I always thought it's CBC? I changed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mode, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result is:

>>> des = DES.new(key)
>>> des.decrypt(data)
'wowhacker@!hine@ipsec\x03\x03\x03'

Remember those '\x03\x03\x03'. You'll see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m again in my crypto challenges ;-).

2. Challenge 10

Challenge 10 is cool. In summary, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 author sets a RSA private key as a property of a Java object, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n he gives out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 serialization stream of that object, and asks teams to recover cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 private key to decrypt a ciphertext.

So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first thing we must do is to understand how Java does serialization. I was never a fan of Java, so this is something completely new to me. But that's why I really enjoy playing capture cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 flag games. It forces me to learn new thing fast in a very short time.

I spent nearly 1 hour reading cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 spec, mostly on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object serialization stream protocol. Then I spent one and a half hour starring at my hex editor screen and acting as a binary parser which was, I don't know why I feel that, really fun (later on Tora of SexyPwndas fame showed me a much less painful way to recover cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object. Thanks Tora!)

I recovered cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RSA private key eventually. How to use it to decrypt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ciphertext in key.txt? While de-serializing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object, you would see that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re's a field named tripleDesKey containing a 24-bit string which you can get by base64-decoding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last 32 bytes of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 serialized object.

At first I thought I should use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RSA key to decrypt this 24-bit string to get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real tripleDesKey, and uses that key in turn to decrypt key.txt. This hybrid approach is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 standard way to do encryption using public key cryptosystem. But you shouldn't expect anything standard in CTF, rite?

It turns out all that tripleDes key and ciphertext are just cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re to distract me. I have to admit that I don't like challenges giving false trails. You can eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r give good trails or no trail at all. Giving false trail is a sin :-P.

Anyway, if you look at key.txt, you'll see that its content is a 128-bytes string. 128-bytes = 1024-bit = cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 modulus in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recovered RSA private key. So this string should be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ciphertext encrypted directly using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RSA private key. Indeed it is!

>>> from M2Crypto.RSA import *
>>> rsa = load_key('my_rsa_key')
>>> data = open('key.bin').read()
>>> rsa.private_decrypt(data, 3)
'\x00\x02#padding#x00isec@#$wowhacker!!'

There's a small minor issue that I intentionally left out. Can you find out what it is and resolve it yourself?

I hope you enjoy reading this. Happy hacking!

Comments

Unknown said…
Thank for your writing.
I am very happy for your enjoy hacking contest.
See you September in Korea.
Tora said…
Nice job!
I'll be waiting for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 level12 writeup xD
Unknown said…
anh ơi hack dùm e ít tiền trong nhà hàng vui vẻ nhé!!!!!!!http://me.zing.vn/jusethieu/home