Tags: python reverse_engineering pyinstaller pyinstxtractor 

Rating:

Skills involved: Reversing exe created by PyInstaller

This challenge is clear about what to do. Some research is needed for the exact tools.

Solution:

We are given an exe so maybe it's a good idea to move it to a Windows machine:

image

The fact that this exe was written in Python can be either found by the method above, or by strings command:

image

Upon basic research we can guess that pyinstaller is used for packing the Python code as an .exe. This can be further confirmed by grepping the strings output:

image

Again upon basic research I arrived at this pyinstall .pyc extractor. It is very easy to use.

image

We only need the Matrix_Lab.pyc file, which we can pass to another very useful site: https://www.decompiler.com/

# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 2.7.17 (default, Sep 30 2020, 13:38:04) 
# [GCC 7.5.0]
# Warning: this version of Python has problems handling the Python 3 "byte" type in constants properly.

# Embedded file name: Matrix_Lab.py
print('Welcome to Matrix Lab 2! Hope you enjoy the journey.')
print('Lab initializing...')
try:
    import matlab.engine
    engine = matlab.engine.start_matlab()
    flag = input('Enter the lab passcode: ').strip()
    outcome = False
    if len(flag) == 23 and flag[:6] == 'SEKAI{' and flag[-1:] == '}':
        A = [ord(i) ^ 42 for i in flag[6:-1]]
        B = matlab.double([A[i:i + 4] for i in range(0, len(A), 4)])
        X = [list(map(int, i)) for i in engine.magic(4)]
        Y = [list(map(int, i)) for i in engine.pascal(4)]
        C = [[None for _ in range(len(X))] for _ in range(len(X))]
        for i in range(len(X)):
            for j in range(len(X[i])):
                C[i][j] = X[i][j] + Y[i][j]

        C = matlab.double(C)
        if engine.mtimes(C, engine.rot90(engine.transpose(B), 1337)) == matlab.double([[2094, 2962, 1014, 2102], [2172, 3955, 1174, 3266], [3186, 4188, 1462, 3936], [3583, 5995, 1859, 5150]]):
            outcome = True
    elif outcome:
        print('Access Granted! Your input is the flag.')
    else:
        print('Access Denied! Your flag: SADGE{aHR0cHM6Ly95b3V0dS5iZS9kUXc0dzlXZ1hjUQ==}')
except:
    print('Unknown error. Maybe you are running the lab in an unsupported environment...')
    print('Your flag: SADGE{ovg.yl/2M6pWQB}')

For the technical part, I used the online matlab engine to understand the various operations. It's possible to use sage or numpy while reading matlab's documentation but I figured that it's faster that way, also I can't really remember those steps.

Finally XORing all values with 42 gives the final flag body.

Original writeup (https://github.com/RaccoonNinja/Project-SEKAI-CTF-2022-Writeups/blob/main/reverse/Matrix%20Lab%202.md).