← Back to Writeups
CUSTOMMediumReversing

Файлы PYC (PYC Files)

XESXOR9/2/20262 min read
#reversing#custom#medium#array-manipulation-analysis#python-bytecode-decompilation-#xor-cipher-reversal#linux

Файлы PYC (PYC Files)

Platform: hackerlab | Category: Reversing | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2025-12-27 | Status: Solved Techniques: Array manipulation analysis, Python bytecode decompilation with uncompyle6, XOR cipher reversal

Summary

Task: Decompile a .pyc file and recover the flag. Solution: Used uncompyle6 to decompile Python 3.8 bytecode, analyzed XOR verification logic, and recovered the flag by XORing reversed byte arrays.

Файлы PYC (PYC Files) — HackerLab

Description

Я потерял свой код проверки флага, но зато нашел PYC файл =D

Given file task.cpython-38.pyc — compiled Python 3.8 bytecode.

Analysis

Step 1: File Identification

bash
file task.cpython-38.pyc
# task.cpython-38.pyc: python 3.8 byte-compiled

The filename cpython-38 indicates Python 3.8.

Step 2: Bytecode Decompilation

bash
uncompyle6 task.cpython-38.pyc

Decompiled code:

python
randb = b'\\;\xfe\xf5E\xff]\xe3\xc3i\xa0\x07\xacO\x97\xb9k\x8f'
enc = b'!|\x90\xc4.\xa0n\x88\xf7\x07\xf3|\xf5\r\xd2\xfd$\xcc'
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

enc = enc[::-1]
randb = randb[::-1]

flag = input("Enter flag: ")

if len(flag) != len(enc):
    print("Wrong!")
    exit()

for i in range(len(flag)):
    if enc[i] ^ randb[i] != ord(flag[i]):
        print("Wrong!")
        exit()

print("Correct!")

Step 3: Verification Logic Analysis

Flag verification algorithm:

  1. Two byte arrays randb and enc (18 bytes each)
  2. Both arrays are reversed using [::-1]
  3. Check: enc[i] ^ randb[i] == ord(flag[i]) for each character

This means: flag[i] = chr(enc[i] ^ randb[i]) ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 4: Flag Recovery

To obtain the flag, perform XOR between the reversed arrays:

python
randb = b'\\;\xfe\xf5E\xff]\xe3\xc3i\xa0\x07\xacO\x97\xb9k\x8f'
enc = b'!|\x90\xc4.\xa0n\x88\xf7\x07\xf3|\xf5\r\xd2\xfd$\xcc'

# Reverse arrays
enc = enc[::-1]
randb = randb[::-1]

# XOR to get the flag
flag = bytes([e ^ r for e, r in zip(enc, randb)])
print(flag.decode())

Result: CODEBY{REDACTED}

Solution

python
#!/usr/bin/env python3
"""
Solution for "Файлы PYC" (PYC Files) task
HackerLab - Reverse Engineering
"""
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Byte arrays from decompiled code
randb = b'\\;\xfe\xf5E\xff]\xe3\xc3i\xa0\x07\xacO\x97\xb9k\x8f'
enc = b'!|\x90\xc4.\xa0n\x88\xf7\x07\xf3|\xf5\r\xd2\xfd$\xcc'

# Reverse arrays (as in original code)
enc = enc[::-1]
randb = randb[::-1]

# XOR to recover the flag
# From verification: enc[i] ^ randb[i] == flag[i]
# Therefore: flag[i] = enc[i] ^ randb[i]
flag = bytes([e ^ r for e, r in zip(enc, randb)])

print(f"Flag: {flag.decode()}")
# CODEBY{REDACTED}

Tools

uncompyle6

Decompilation of Python 2.7-3.8 bytecode:

bash
pip install uncompyle6
uncompyle6 file.pyc > file.py

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Alternatives for Different Python Versions

Python VersionTool
2.7 - 3.8uncompyle6
3.9+pycdc, decompyle3
Anypycdc (C++ based)

pycdc

Universal decompiler:

bash
git clone https://github.com/zrax/pycdc.git
cd pycdc && cmake . && make
./pycdc file.pyc

XOR Flag Verification Pattern

Typical pattern in CTF tasks:

python
# Encryption
ciphertext[i] = plaintext[i] ^ key[i]

# Decryption (XOR is self-inverse)
plaintext[i] = ciphertext[i] ^ key[i]

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

In this task:

  • enc — encrypted flag
  • randb — XOR key
  • flag = enc ^ randb ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍