Pwn2win2020 Androids Encryption
Challenge Info
The challenge is a crypto challenge from the pwn2win event , it’s focused on the symmetric cryptography and especially the aes block cipher.So we are given remote connection nc encryption.pwn2.win 1337
and the python script that is running in the remote server.py
.
Writeup Summary
-
gain general information
-
deep look into encrypt your secret
-
Solution
gain general information
By the first look at the server.py
script we notice there are 3 main functions first one is def encrypt(txt, key, iv)
where you pass the plaintext the key and iv this function will check that the plaintext length is multiple of Block Size which is 128 and then it will encrypt the plaintext with custom implementation of AES , the second one is enc_plaintext
this function that we will interact with it will take our plaintext and decode it as a base64 and pass it to encrypt
with key1
and iv1
which are secrets . The last function is enc_flag()
it will encrypt the flag with key2
and iv2
which their difinition is :
|
|
by looking at the xor
function we noticed that if two parametres a,b
are passed then it will calculate a xor b
else if one parametre a
is passed it will return a[0] xor \x00 *len(a[0])
so it will return the first block xored with 00 and that meen it will return the first block .
deep look into encrypt your secret
After looking in the function i noticed it doing 2 things interesting :
-
first thing is that it is returning to us the iv passed in parametre + the cipher so for example if we passed
iv2
to the function than we get as a resultiv2+ cipher
1
base64.b64encode(iv+ctxt)
PS: of course all inputs and outputs are encoded with base64
-
the second interesting thing is that it is overriding the
iv2
andkey2
that are used in encrypting the flag :1 2
iv2 = AES.new(key2, AES.MODE_ECB).decrypt(iv2) key2 = xor(to_blocks(ctxt))
so the new
iv2
is the decryption of the previousiv2
withkey2
and the newkey2
is the xor of the cipher calculated and as we have discussedxor
function when we pass one parametre it will return the first block of the passed object sokey2 = cipher[0]
so from the resultiv+ctx
we can getiv1
andkey2
from the cipher and to get the next value ofiv2
we need the value ofkey2
before change .so the idea of the challenge is to try to guess theiv2
andkey2
that will be used next time we encrypt the flag .
Solution
after trying in a paper the different combination of commandes that will allow us to get the key and initial vector i finnaly found the solution it is bit tricky so what we will do is :
-
we will send a random payload with 16 bytes to the oracle that will return us
iv1 + cipher
and from the cipher we can get the new valuekey2
because as we saidkey2 = a[0]
the new key is the first block of cipher -
next we will send the encrypt flag command that will return to us
iv2 + flag_cipher
and here we can use the result of the first step which is key2 and get the new value ofiv2
because it will be changed byiv2 = AES.new(key2, AES.MODE_ECB).decrypt(iv2)
and also we update the value ofkey2
now we have thekey2
andiv2
values and we can use it to decipher the flag next time because this value will be used next time -
we will send the encrypt flag command and decrypt the cipher :
1 2 3 4 5 6 7 8
aes = AES.new(key2, AES.MODE_ECB) curr = iv2 bs = len(key2) text=b"" for block in blocks: text +=xor(curr, aes.decrypt(block)) curr = xor(text[-bs:], block) print(text)
the challenge used a modified version of aes ecb it work like this
cipher1 = aes(text1 xor iv)
thencipher2 = aes(text2 xor (text1 xor cipher1))
and it do this for each block . so for the decryption part we can do thistext1 = iv xor aes.decrypt(cipher1)
and for other blockstextI= (cipherJ xor textJ) xor aes.decrypt(cipherI)
whereJ = I-1
.
and finnaly we got the flag CTF-BR{kn3W_7h4T_7hEr3_4r3_Pc8C_r3pe471ti0ns?!?}
. awesome challenge had so much fun solving it .