ECSC pre quals - Pytector (reverse)

From the 13 to 22 of May 2019, the ANSSI (National Cybersecurity Agency of France) organized the pre qualification for the European Cybersecurity Challenge (ECSC).

 

We were about 1200 attempting this CTF to be in the first 25 peoples to be pre qualified for the final taking place during Le Hack in July.

 

As I m 20 I was competiting as Junior, however I first decided to not do this CTF because I was really really busy because of school and the CTF I organized. 

 

But Fortunatly two friend beat my ass and almot forced me to do some chall in order to get a chance.

 

So I decided to do it 2 days and I pwned 11 challenges all quite easy or arm pwn and a nice reverse challenge (this challenge). Hopefully I get pre qualified even if I ranked 101 ...

 

 

   

Difficulty: hard 

file.zip

 

From PE to PY

A zip was provided for this challenge, it contained a directory named "dist" with the following files :

VCRUNTIME140.dll:           PE32 executable (DLL) (console) Intel 80386, for MS Windows
_bz2.pyd:                   PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
_hashlib.pyd:               PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
_lzma.pyd:                  PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
_socket.pyd:                PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
_ssl.pyd:                   PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
base_library.zip:           Zip archive data, at least v2.0 to extract
check_serial.exe:           PE32 executable (console) Intel 80386, for MS Windows
libcrypto-1_1.dll:          PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
libssl-1_1.dll:             PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
pyexpat.pyd:                PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
pytector.pyd:               PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
python37.dll:               PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
select.pyd:                 PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
unicodedata.pyd:            PE32 executable (DLL) (GUI) Intel 80386, for MS Windows

As you see a there is a lot of DLL and a PE which is our binary that we want to reverse. In fact this is a Python script which has been frozen with cx_freeze, py2exe or pyinstaller. The creator of the challenge used python 3.7 it will be useful a bit later.

 

As often I used to open the PE with IDA but the amount of functions quickly discouraged me so I went check some CTF write up about frozen script. At this time I quickly wanted to know if they were some kind of entry point to start reversing this kind of file


I went through a write up for the Malwarebytes challenge 2018 I read a few time ago. It mentioned an unpacker which could extract compiled python from the binary let's give a check : python-exe-unpacker

 

ackira /mnt/hgfs/nextcloud/CTF/ECSC/reverse/check_serial2/dist $ python3.7 ~/tools/reverse/python-exe-unpacker/pyinstxtractor.py check_serial.exe

[*] Processing check_serial.exe
[*] Pyinstaller version: 2.1+
[*] Python version: 37
[*] Length of package: 1177687 bytes
[*] Found 7 files in CArchive
[*] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap
[+] Possible entry point: fake_check
[*] Found 133 files in PYZ archive
[*] Successfully extracted pyinstaller archive: check_serial.exe

 

Something very important about this script is to use the same exact version of python to execute it than the python version used to compiled it, else the extraction will not be complete and you will have the following errors :

 

ackira /mnt/hgfs/nextcloud/CTF/ECSC/reverse/check_serial2/dist $ python ~/tools/reverse/python-exe-unpacker/pyinstxtractor.py check_serial.exe
[*] Processing check_serial.exe
[*] Pyinstaller version: 2.1+
[*] Python version: 37
[*] Length of package: 1177687 bytes
[*] Found 7 files in CArchive
[*] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap
[+] Possible entry point: fake_check
[!] Warning: The script is running in a different python version than the one used to build the executable
   Run this script in Python37 to prevent extraction errors(if any) during unmarshalling
[!] Unmarshalling FAILED. Cannot extract PYZ-00.pyz. Extracting remaining files.
[*] Successfully extracted pyinstaller archive: check_serial.exe

 

I doubt it's because of the marshal format. Unlike the pickle format, the marshal format is changing through the python version and is not documented.

 

"Details of the format are undocumented on purpose; it may change between Python versions (although it rarely does)."

 from the python doc

 

Each version has it own magic bytes (to be finished)