1337UP was a 24 hours long CTF was organized by Intigriti . I personally solved a couple of challenges in the web and cryptography category, but I’ll be posting writeups only for cryptography challenges. So let’s start with something easy.
The warmup encoder problem was an easy problem to solve (hence the name “warmup”). The challenge provided a python file (encrypt.py) with the logic of encrypting the flag and the encrypting result of the flag. our job is to decrypt the provided result, so we can see the flag.
encrypt.py
from sympy import isprime, primeflag = '<redacted>'def Ord(flag):
x0r([ord(i) for i in flag])
def x0r(listt):
ff = []
for i in listt:
if isprime(i) == True:
ff.append(prime(i) ^ 0x1337)
else:
ff.append(i ^ 0x1337)
b1n(ff)def b1n(listt):
ff = []
for i in listt:
ff.append(int(bin(i)[2:]))
print(ff)
if __name__ == "__main__":
Ord(flag)'''
OUTPUT :
[1001100000110, 1001100000100, 1001100000100, 1001100000000, 1001101100010, 1001101100111, 1001101001100, 1001101001111, 1001100000111, 1001101000101, 1001101101000, 1001100000011, 1001101011001, 1001101110011, 1001101101000, 1001101110101, 1001101011110, 1001101011001, 1001100000011, 1001011001010, 1001101100101, 1001101001110, 1001101101000, 1001101110010, 1001101011001, 1001001111100, 1001100000111, 1001101010011, 1001100000100, 1001101000101, 1001101101000, 1001100000011, 1001101000101, 1001100000100, 1001101101000, 1001101000011, 1001101111111, 1001100000100, 1001101101000, 1001101100000, 1001100000100, 1001100000011, 1000101111100, 1001100000100, 1001111000110, 1001101000011, 1001101101000, 1001100001111, 1001100000111, 1001100000000, 1001100001110, 1001100000111, 1001100000000, 1001111000110, 1001100000001, 1001101001010]
'''
let’s understand each function’s logic and try to reverse its doing.
0rd
function:
- It’s taking the flag (which is redacted in the given file) and converting each character of the flag to its Unicode code point using the ord() function. e.g. ord(‘a’) = 97
- storing each Unicode code point to a list and passing that to
x0r
function.
x0r
function:
- It’s iterating the given list, checking if i’th iterating number (which is Unicode code point) is prime and if it’s prime then perform bitwise xor(^) between i’th prime number and
0x1337
, and append to a list. e.g if i’th number is 3 then perform bitwise xor between 3rd prime i.e. 5 and0x1337
- If i’th iterating number isn’t prime, then just perform bitwise xor(^) between i’th number and
0x1337
, and append to the list. - Finally, call
b1n
the function with the result list.
b1n
function:
- It’s iterating the given list and converting each value (i.e. decimal number) of the list to a binary number using the bin() function and removing the prefix
0b
from it. - then converting that to an integer and appending it to a list.
This final list is what we’re given. Now that we understand what each function does, let’s see what their reverse logic will be to undo their doing.
reverse logic of b1n
function:
- we need to convert each integer to a string with
0b
prefix and then convert it decimal number. And store them in a list.
ff = []
for i in flag:
w = '0b' + str(i)
ff.append(int(w, 2))
reverse logic of x0r
function:
- Take each decimal number and perform bitwise xor(^) operation to it with
0x1337
to get original input again. This is one of the xor properties i.e. inverse of xor is xor itself. e.g. if you havea=b^c
, you can getb
orc
back if another value is available.b=a^c
orc=a^b
. - Now, we’ll check if the result decimal number is any of the first 200 prime numbers (a range of 200 will be enough). If it is, then will put
n
(of n’th prime number, e.g. if it is 3rd prime number, then 3) to a list. If it isn’t, then will add the result integer to that list.
ff1 = []
for i in input:
w = i ^ 0x1337
isthat = get_nth(w) #this returns n if w is nth prime
if isthat == None:
ff1.append(w)
else:
ff1.append(isthat)
reverse logic of 0rd
function:
- Now, we have a list of integers which are Unicode code integers. We will take each integer and convert it to character using chr() function (ord() does opposite of that)and after concatenating all characters, we will have our flag.
ori_flag = ''
for i in ff2:
ori_flag = ori_flag + chr(i)
print(ori_flag)
The final code looks like this:
decrypt.py
from sympy import isprime, primeflag = [1001100000110, 1001100000100, 1001100000100, 1001100000000, 1001101100010, 1001101100111, 1001101001100, 1001101001111, 1001100000111, 1001101000101, 1001101101000, 1001100000011, 1001101011001, 1001101110011, 1001101101000, 1001101110101, 1001101011110, 1001101011001, 1001100000011, 1001011001010, 1001101100101, 1001101001110, 1001101101000, 1001101110010, 1001101011001, 1001001111100, 1001100000111, 1001101010011, 1001100000100, 1001101000101, 1001101101000, 1001100000011, 1001101000101, 1001100000100, 1001101101000, 1001101000011, 1001101111111, 1001100000100, 1001101101000, 1001101100000, 1001100000100, 1001100000011, 1000101111100, 1001100000100, 1001111000110, 1001101000011, 1001101101000, 1001100001111, 1001100000111, 1001100000000, 1001100001110, 1001100000111, 1001100000000, 1001111000110, 1001100000001, 1001101001010]# reverse of b1n()
def rev_b1n(flag):
ff = []
for i in flag:
w = '0b' + str(i)
ff.append(int(w, 2))
rev_x0r(ff)# reverse of x0r()
def rev_x0r(input):
ff1 = []
for i in input:
w = i ^ 0x1337
isthat = get_nth(w)
if isthat == None:
ff1.append(w)
else:
ff1.append(isthat)
rev_Ord(ff1)# Returns i if num is ith prime, None otherwise
def get_nth(num):
for i in range(1,200):
if prime(i) == num:
return i# reverse of rev_0rd()
def rev_Ord(ff2):
ori_flag = ''
for i in ff2:
ori_flag = ori_flag + chr(i)
print(ori_flag)if __name__ == "__main__":
rev_b1n(flag)
Note that the calling of reverse logic functions in decrypt.py is also reversed of calling original functions in encrypt.py. This is obvious because the process needs to be reversed to decrypt the flag.
flag : 1337UP{x0r_4nD_Bin4aRy_EnC0d3r_4r3_tH3_W34k35t_80790756}
I have been learning cryptography using cryptohack platform. Check that out if you’re also interested in cryptography. Feel free to connect on Twitter. @0verread. You can DM me over there if you have any questions or just want to chat about something interesting.
I will be posting writeups for other crypto challenges as well. Until then, take care.