Crypto 100 Another xor - By Nazime
Challenge :
Description of chall : Hey, hey can you find my secret. UPDATE 10:13 Eastern: the flag is whatever is in sys.argv[2]
Analyse :
we have an encrypted cipher and the algorithme of encryption.ciphertext = [plaintext+key+md5(plaintext+key)] XOR [key]
The first thing we can notice is that the key is xored with itself
plaintext.key.md5(plaintext.key)
key.key.key.key.key.key.key.key.k ....
The lentgh of the encrypted file is 137
cipher = open("encrypted").read().decode("hex")
print len(cipher) # 137
Solution :
For my solution i didn't use the md5 hash (i should) , knowing that the hash have 32 caracters i only work with the 105 first caracter (plaintext+key)
befor explaing the solution let's take an easy other exemple :
we have our plaintext+key encrypted with the key, and we only know that
- len (plaintext + key) = 10
- len (key) = 3
- we know the ciphertext
- we know the first letter of our plaintext "s"
With all those informations and with the proprity of xor (a xor b = c => c xor b = a , so plaintext xor key = cipher, cipher xor key = plaintext , cipher xor plaintext = key)
we have (* for plaintext and - for key)
we have the first letter of plaintext "s" and the first letter of cipher text "c" if we xor "s" with "c" we will have the first letter of the key "k"
s******---
k---------
ciphertext
we know that the length of key is 3, and we have the first letter, and the key is repeating again and again so we can fill some gaps******---
k--k--k--k
ciphertext
we know that after the plaintext they have a key, and the lentgh of the plaintext is 7 so the the first letter of the key must be at position 8
s******k--
k--k--k--k
ciphertext
we have some caracter in the key and some other in the plaintext let's xor them for having other caracters**r**sk-y
k--k--ke-k
ciphertext
Now we have the second caracter of the key "e" , and the third one "y" so we fill the gaps**r**skey
keykeykeyk
ciphertext
we xor one last time
secretskey
keykeykeyk
ciphertext
and we have our plaintext "secrets" and ou key "key", now for our solution we'll do the same 3 steps xoring, expend the key , add the key after the plaintext again and again.
so now we have
- the start of our flag must be "flag{" we know 5 caracters
- Xoring the 5 caracters of our flag with cipher we got the 5 first caracters of our key
- the key and the flag must be printible ASCII caracter (if not we skip to the next length of key)
- all the cipher text
- len(plaintext+key) = len(ciphertext) - len(md5) = 137-32 = 105
- length of key must be beetween 6 and 98
Since we don't know the length of our key, we are going to try all possible key's length, and each time we hve something not logic (like having an not having a printable ASCII caracter in our cipher or key) we test the next length
PS : i could use the information that an md5 hash have only hexadicemal caracter for knowing the length.
Python Script
I know that the Plaintext+key is 105 long , so i used a 3 list of 105 character (ciphertext,longkey,plaintext+key) , and implement my own xor function who xor just if we know one value of the key or plaintext otherwise it do nothing and let None in our list, it return False if the caracter is not printible ASCII or if xor(key,plain) != cipher
The full script here.