Writeup: FlareOn 2022: 011 - the challenge that shall not be named
1. TLDR
2. Dane wejściowe
Plik z zadaniem znajduje się tutaj. Hasło: flare.
Przedmiotem zadania był plik:
11.exe
Zweryfikowałem typ pliku 11.exe
:
$ file 11.exe
11.exe: PE32+ executable (console) x86-64, for MS Windows
3. Analiza wstępna
Wczytałem program do IDA. Po krótkiej analizie znalazłem fragment kodu:
Program był zatem napisany w języku Python i został spakowany do jednego pakietu narzędziem PyInstaller
4. Odpakowanie pakietu
4.1 pyinstxtractor
W celu odpakowania pakietu pobrałem narzędzie pyinstxtractor-ng i je uruchomiłem:
>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
Następnie, w celu dokończenia dekompilacji, uruchomiłem narzędzie uncompyle6:
>uncompyle6 -ro 11.exe_decompiled 11.exe_extracted
Niestety, program był zabezpieczony narzędziem pyarmor
from pytransform import pyarmor
pyarmor(__name__, __file__, b'PYARMOR\x00\x00\x03\x07\x00B\r......\xe8;?\x12S\x16', 2)
5. Deobfuskacja i… odczytanie flagi
Postanowiłem zdeobfuskować projekt, korzystając z PyArmor-Unpacker.
Ze względu na wiadomość na Githubie:
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.
sprawdziłem wersję pythona wykorzystanego przez 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
Zatem wykorzystana wersja pythona to 3.7.
Sprawdziłem wersję zainstalowanego interpretera:
>python --version
Python 3.7.9
Spróbowałem uruchomić plik 11.pyc. Niestety próba zakończyła się niepowodzeniem:
>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'
Moduł crypt jest niedostępny dla Windows
Postanowiłem przetestować w jaki sposób wykorzystywana jest ta biblioteka.
W tym celu utworzyłem plik crypt.py
:
>touch crypt.py
Ponownie spróbowałem uruchomić plik 11.pyc
>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'
Do pliku crypt.py
dopisałem zawartość:
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("[+] ############")
Po uruchomieniu na standardowym wyjściu pojawiła się zawartość:
>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'
Nastąpiło odwołanie do atrybutu encrypt - dostarczyłem zatem programowi, to co ten potrzebował:
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)
Po uruchomieniu na standardowym wyjściu pojawiła się zawartość:
>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'
Zatem flaga to:
Pyth0n_Prot3ction_tuRn3d_Up_t0_11@flare-on.com