Writeup: FlareOn 2022: 011 - the challenge that shall not be named

Task description

1. TLDR

TLDR graph

2. Input data

The task file can be found here. Password: flare.

The subject of the task was a file:

11.exe

I verified the file type ```11.exe``:

$ file 11.exe
11.exe: PE32+ executable (console) x86-64, for MS Windows

3. Initial analysis

I loaded the program into IDA. After a brief analysis, I found a piece of code:

pyinstaller

So the program was written in Python and was packaged into a single package with the PyInstaller tool

4. Unpacking the package

4.1 pyinstxtractor

To unpack the package, I downloaded the pyinstxtractor-ng tool and ran it:

>pyinstxtractor-ng.exe 11.exe
[+] Processing 11.exe
[+] Pyinstaller version: 2.1+
[+] Python version: 3.7
[+] Length of package: 8807847 bytes
[+] Found 80 files in CArchive
[+] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap.pyc
[+] Possible entry point: pyi_rth_subprocess.pyc
[+] Possible entry point: pyi_rth_inspect.pyc
[+] Possible entry point: 11.pyc
[+] Found 250 files in PYZ archive
[+] Successfully extracted pyinstaller archive: 11.exe

You can now use a python decompiler on the pyc files within the extracted directory

4.2 uncompyle6

Then, to complete the decompilation, I ran the uncompyle6 tool:

>uncompyle6 -ro 11.exe_decompiled 11.exe_extracted

Unfortunately, the program was protected by the pyarmor tool

from pytransform import pyarmor
pyarmor(__name__, __file__, b'PYARMOR\x00\x00\x03\x07\x00B\r......\xe8;?\x12S\x16', 2)

5. Deobfuscation and… reading the flag

I decided to deobfuscate the project using PyArmor-Unpacker.

Because of the message on Github:

IMPORTANT: USE THE SAME PYTHON VERSION EVERYWHERE,
LOOK AT WHAT THE PROGRAM YOU ARE UNPACKING IS COMPILED WITH.
If you don't you will face issues.

I checked the version of python used by 11.exe:

$ grep -a python 11.exe
- blibssl-1_1.dll @-F--bpython3.dll @nO9:bpython37.dll0YSWD--bpytransform.pyd ^-6-jbselect.pyd ^--Eibucrtbase.dll0f7-bbunicodedata.pyd0l        QC>
                                                                   %-xbase_library.zip0oL-]-Z&xcertifi\cacert.pem0q-xcertifi\py.typed@q-^
                                                         xcryptography-36.0.1.dist-info\INSTALLER@q-j-Ixcryptography-36.0.1.dist-info\LICENSE@q-=--*xcryptography-36.0.1.dist-info\LICENSE.APACHE@q---xcryptography-36.0.1.dist-info\LICENSE.BSD@q---   -xcryptography-36.0.1.dist-info\LICENSE.PSF@qµ--xcryptography-36.0.1.dist-info\METADATA@q?9>-xcryptography-36.0.1.dist-info\RECORD@q-xcryptography-36.0.1.dist-info\REQUESTED@q--jdxcryptography-36.0.1.dist-info\WHEEL@q-9xcryptography-36.0.1.dist-info\top_level.txt q-Wv-v-zPYZ-00.pyzMEI



-e--S-`3python37.dll

So the version of python used is 3.7.

I checked the version of the installed interpreter:

>python --version
Python 3.7.9

I tried to run the 11.pyc file. Unfortunately, the attempt failed:

>python 11.pyc
Traceback (most recent call last):
  File "<dist\obf\11.py>", line 2, in <module>
  File "<frozen 11>", line 3, in <module>
  File "C:\Python37\lib\crypt.py", line 3, in <module>
    import _crypt
ModuleNotFoundError: No module named '_crypt'

The crypt module is not available for Windows

I decided to test how this library is used. To do this, I created the file crypt.py:

>touch crypt.py

I tried to run the 11.pyc file again:

>python 11.pyc
C:\Python37\lib\site-packages\requests\__init__.py:104: RequestsDependencyWarning: urllib3 (1.26.7) or chardet (5.0.0)/c
harset_normalizer (2.0.9) doesn't match a supported version!
  RequestsDependencyWarning)
Traceback (most recent call last):
  File "<dist\obf\11.py>", line 2, in <module>
  File "<frozen 11>", line 12, in <module>
AttributeError: module 'crypt' has no attribute 'ARC4'

I added the contents to the file crypt.py:

def ARC4(*args, **kwargs):
    print("[+] ### ARC4 ###")
    print(f"[+] {len(args)} args:")
    for arg in args:
        print(f"  [-] {arg}")
    print(f"[+] {len(kwargs.values())} kwargs:")
    for value in kwargs.values():
        print(f"  [-] {value}")
    print("[+] ############")

After running, the standard output showed content:

>python 11.pyc
C:\Python37\lib\site-packages\requests\__init__.py:104: RequestsDependencyWarning: urllib3 (1.26.7) or chardet (5.0.0)/c
harset_normalizer (2.0.9) doesn't match a supported version!
  RequestsDependencyWarning)
[+] ### ARC4 ###
[+] 1 args:
  [-] b'PyArmor_Pr0tecteth_My_K3y'
[+] 0 kwargs:
[+] ############
Traceback (most recent call last):
  File "<dist\obf\11.py>", line 2, in <module>
  File "<frozen 11>", line 15, in <module>
AttributeError: 'NoneType' object has no attribute 'encrypt'

There was a reference to the encrypt attribute - so I provided the program with what it needed:

def print_params(name, *args, **kwargs):
    print("[+] ### {name} ###")
    print(f"[+] {len(args)} args:")
    for arg in args:
        print(f"  [-] {arg}")
    print(f"[+] {len(kwargs.values())} kwargs:")
    for value in kwargs.values():
        print(f"  [-] {value}")
    print("[+] ############")

class ARC4:
    def __init__(*args, **kwargs):
        print_params("ARC4", *args, **kwargs)

    def encrypt(*args, **kwargs):
        print_params("encrypt", *args, **kwargs)

After running, the standard output showed content:

>python 11.pyc
C:\Python37\lib\site-packages\requests\__init__.py:104: RequestsDependencyWarning: urllib3 (1.26.7) or chardet (5.0.0)/c
harset_normalizer (2.0.9) doesn't match a supported version!
  RequestsDependencyWarning)
[+] ### {name} ###
[+] 2 args:
  [-] <crypt.ARC4 object at 0x00000000006BC808>
  [-] b'PyArmor_Pr0tecteth_My_K3y'
[+] 0 kwargs:
[+] ############
[+] ### {name} ###
[+] 2 args:
  [-] <crypt.ARC4 object at 0x00000000006BC808>
  [-] b'Pyth0n_Prot3ction_tuRn3d_Up_t0_11@flare-on.com'
[+] 0 kwargs:
[+] ############
Traceback (most recent call last):
  File "<dist\obf\11.py>", line 2, in <module>
  File "<frozen 11>", line 15, in <module>
  File "C:\Python37\lib\base64.py", line 58, in b64encode
    encoded = binascii.b2a_base64(s, newline=False)
TypeError: a bytes-like object is required, not 'NoneType'

Thus, the flag is:

Pyth0n_Prot3ction_tuRn3d_Up_t0_11@flare-on.com