This is the Qualification phase for ASC War Games at Egypt. There was 5 crypto challenges in the competition and I’ll go through the Challenge2, the most interesting one for me.
Analyzing the challenge
The challenge give us 2 files
challenge.py
script contains the encryption algorithm and
output.txt
. the
output.txt
file contains
temp
and
cipher
variables.
So, let’s look at the script file that was given.
After looking at the script, It has 3 functions :
-
encrypt(plain, key)
: It’s just createAES
instanse and returnbase64
of the encrypted text with a given key. -
choose_random(length=1)
: This function return 2 bytes random string given a specified length or 1 random byte as a default value. -
generate_random()
: Same as the above but it just returns 4 bytes random string.
Then, the script generates 2 bytes keys, repeat that 8 times,
and put them into a list of
all_keys
. After that, it performs 9 encryption operations on some data
in
temp.txt
file.
So, the vulnerability here is it encrypts the hex value of the data not on the raw bytes itself and we can take advantage of that by checking the decryption upon every possible subkey of length 2 is hex values if so, then we got the correct subkey.
Note that:
- The last operation 9 it performs the same process but on the key of length 4, so let’s first get the 4 bytes key.
- All the keys that is being used are repeated to be 16 bytes long.
After analyzing the bruteforce search space we got
len(printable) = 100
, therefore 4 bytes string has
100*100*100*100 = 10^8
possible key values and 2 bytes string has
100*100 = 10000
possible values. So, it’s feasible to bruteforce the keys with
the
itertools
library in python.
Cracking the 4 bytes key
I wrote some python script to get all the possible combination of the 4 bytes key and try them.
I got the first big key
099!099!099!099!
and now the value
C8
can
be used to get
Ci
where
0 <= i <= 7
and
C0
is
the original
temp
plain text.
Cracking all the 2 bytes keys
Before running the following script I got a one byte value
problem from the
dec
variable while decrypting the
Ci
. So
let’s check if the decryption string is greater than 1 by
editing the
run
function and put
if is_hex(dec) and len(dec) > 1:
And now we got all the keys.
The flag
Because we’ve been decrypting from
C9
,
let’s reverse them and put them together as the final key to get
the flag.
Eventually, the flag is here.