Tags: reverse 

Rating: 4.3

image
obscure.zip

The file is a python byte-compiled file.

image

To decompile, rename as .pyc and run uncompyle6 and we get the following:

# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:43:08) [MSC v.1926 32 bit (Intel)]
# Embedded file name: reverseme.py
# Compiled at: 2021-09-04 17:21:21
import numpy as np
flag = 'TamilCTF{this_one_is_a_liability_dont_fall_for_it}'
np.random.seed(369)
data = np.array([ ord(c) for c in flag ])
extra = np.random.randint(1, 5, len(flag))
product = np.multiply(data, extra)
temp1 = [ x for x in data ]
temp2 = [ ord(x) for x in 'dondaVSclb' * 5 ]
c = [ temp1[i] ^ temp2[i] for i in range(len(temp1)) ]
flagdata = ('').join(hex(x)[2:].zfill(2) for x in c)
real_flag = '300e030d0d1507251700361a3a0127662120093d551c311029330c53022e1d3028541315363c5e3d063d0b250a090c52021f'
# okay decompiling reverseme.pyc

In the above code, we can see an encryption algorithm running on a sample flag TamilCTF{this_one_is_a_liability_dont_fall_for_it}. If we were to print(flagdata), we get:

300e030d0d15072517160c061d3b0e38363c05113b0e31080837310a000b101631000e38273c0a03080331020e240c0a181f

This format is the same as that of real_flag, but the values differ. We need to reverse the encryption algorithm and pass in the flagdata of real_flag to get the actual flag.

We can adopt a bruteforce approach whereby we pass every printable ascii character through the algorithm and get the output, then compare it with the ciphertext to map out the ascii flag.

But first, we should explore the encryption algorithm. In the example below, encrypting the letter T gives us 30 which corresponds to the first 2 digits of the flagdata of real_flag. Since we know the flag format is TamilCTF{}, we can proceed to encrypt the next letter a, and we should expect 0e, which is the next 2 digits of flagdata. However, we are given 05 instead. Strange.

real_flag = '300e030d0d1507251700361a3a0127662120093d551c311029330c53022e1d3028541315363c5e3d063d0b250a090c52021f'
"T" : 30
"a" : 05

Upon further exploration, I realised that the characters has to be in the correct index before encryption will tally. Here, the letter a is at the 2nd position and the result is 0e as expected.

"Ta" : 300e
"TamilCTF{" : 300e030d0d15072517

Thus, we create a string called flag_decrypted. We append a printable ascii character and compare it with the algorithm. If output matches with real_flag(truncated), continue with the next position, else, revert back to the original string and try a different ascii character. Since we know the flag format, we can start off with TamilCTF{. This is the final code:

import numpy as np
def algo(flag):
    np.random.seed(369)
    data = np.array([ ord(c) for c in flag ])
    extra = np.random.randint(1, 5, len(flag))
    product = np.multiply(data, extra)
    temp1 = [ x for x in data ]
    temp2 = [ ord(x) for x in 'dondaVSclb' * 5 ]
    c = [ temp1[i] ^ temp2[i] for i in range(len(temp1)) ]
    flagdata = ('').join(hex(x)[2:].zfill(2) for x in c)
    return flagdata

flag = 'TamilCTF{this_one_is_a_liability_dont_fall_for_it}'
flag_length = len(flag)
real_flag = '300e030d0d1507251700361a3a0127662120093d551c311029330c53022e1d3028541315363c5e3d063d0b250a090c52021f'

import string
ascii_list = string.printable

flag_decrypted = "TamilCTF{"

for y in range(len(flag_decrypted),flag_length):
    temp_flag = flag_decrypted
    for sym in ascii_list:
        temp_flag+=sym #try ascii char
        if algo(temp_flag) == real_flag[:2*y]: #check against truncated real_flag
            flag_decrypted = temp_flag #append correct char
        else:
            temp_flag = flag_decrypted #go back to original
            continue
    print(flag_decrypted)

flag_decrypted+="}"
print(flag_decrypted)

We get the following output:

TamilCTF{
TamilCTF{b
TamilCTF{bR
TamilCTF{bRu
TamilCTF{bRuT
TamilCTF{bRuTe
TamilCTF{bRuTeF
TamilCTF{bRuTeF0
TamilCTF{bRuTeF0r
TamilCTF{bRuTeF0rC
TamilCTF{bRuTeF0rCe
TamilCTF{bRuTeF0rCe_
TamilCTF{bRuTeF0rCe_1
TamilCTF{bRuTeF0rCe_1s
TamilCTF{bRuTeF0rCe_1s_
TamilCTF{bRuTeF0rCe_1s_t
TamilCTF{bRuTeF0rCe_1s_tH
TamilCTF{bRuTeF0rCe_1s_tHe
TamilCTF{bRuTeF0rCe_1s_tHe_
TamilCTF{bRuTeF0rCe_1s_tHe_0
TamilCTF{bRuTeF0rCe_1s_tHe_0n
TamilCTF{bRuTeF0rCe_1s_tHe_0nL
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0r
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rC
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_b
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bR
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bRe
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bReA
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bReAk
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bReAk_
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bReAk__
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bReAk__1
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bReAk__1n
TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bReAk__1n}

TamilCTF{bRuTeF0rCe_1s_tHe_0nLy_F0rCe_2_bReAk__1n}

Original writeup (https://github.com/Rookie441/CTF/blob/main/Storage/Writeups/TamilCTF2021_Writeup.md#obscure).