It has been more than a quarter since the last post, and in the meantime, I was very busy and did not have the time to write a proper post. The good news is at the moment, I am comparatively free and can put in a quick post.
As said earlier, PyInstaller provides an option to encrypt the embedded files within the executable. This feature can be used by supplying an argument --key=key-string while generating the executable.
Detecting encrypted pyinstaller executables is simple. If pyinstxtractor is used, it would indicate this as shown in Figure 1.
![]() |
Figure 1: Trying to extract encrypted pyinstaller archive |
The other tell-tale sign is the presence of the file pyimod00_crypto_key in the extracted directory as shown in Figure 2.
![]() |
Figure 2: The file pyimod00_crypto_key indicates usage of crypto |
If encryption is used, pyinstaller AES encrypts all the embedded files present within ZLibArchive i.e. the out00-PYZ.pyz file. When pyinstxtractor encounters an encrypted pyz archive, it would extract the contents as-is without decrypting the individual files as shown in Figure 3.
![]() |
Figure 3: Contents of an encrypted pyz archive |
To decrypt the files, you would need the key, and the key is present right within the file pyimod00_crypto_key. This is just a pyc file, and can be fed to a decompiler to retrieve the key.
With the key in hand, it is a matter of another script to decrypt.
from Crypto.Cipher import AES
import zlib
CRYPT_BLOCK_SIZE = 16
# key obtained from pyimod00_crypto_key
key = 'MySup3rS3cr3tK3y'
inf = open('_abcoll.pyc.encrypted', 'rb') # encrypted file input
outf = open('_abcoll.pyc', 'wb') # output file
# Initialization vector
iv = inf.read(CRYPT_BLOCK_SIZE)
cipher = AES.new(key, AES.MODE_CFB, iv)
# Decrypt and decompress
plaintext = zlib.decompress(cipher.decrypt(inf.read()))
# Write pyc header
outf.write('\x03\xf3\x0d\x0a\0\0\0\0')
# Write decrypted data
outf.write(plaintext)
inf.close()
outf.close()
The above snippet can be used for decrypting the encrypted files. Afterward, you can run a decompiler to get back the source.
Thank you very much! :)
ReplyDeleteWhat about when there is not a pymod00_crypto_key file at all?
ReplyDeleteThis probably means a modified version of pyinstaller has been used. Look, if the application runs without asking for a key it must have the key embedded within it somewhere. You would need to find where.
DeleteI have the key and the files. But then I am stuck. Am a windows user, but have python 3 installed. But above snip fails with me. I need the python code for a very small program I use, but the HDD drive with the source py files are dead.
ReplyDeleteCan we contact eachother, or can you help me here?
You should elaborate a bit about the exact error you are facing.
DeleteFor contact, you can use my email on the "About Me" page.
I would use your "About me", but it is empty. :-)
DeleteI get stuck at your last picture. I dont know have to use that code. I have a folder with *.pyc.encryptet files I need decryptet.
How I can extract the main.py file(xxx.exe.manifest & xxx)? The file in unpacket folder, not in "out00-PYZ.pyz_extracted".
ReplyDeleteHi, you can ignore the manifest. Try decompiling the "xxx" file. If it works, you're good to go. If not, you may need to fix the file header. Check the "Reversing a PyInstaller based ransomware" post.
Delete