Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unpacking PyInstaller packed files

Tags:

python

I currently have a PyInstaller packed Elf file and I'm looking to unpack it into the original .py file(s). I have been using PyInstaller Extractor but it appears to be telling the archive is not a PyInstaller archive.

Here is an example of what I've been doing:

$ cat main.py
#! /usr/bin/python3
print ("Hello %s" % ("World"))

I pack it in the file dist/main/main with the command:

pyinstaller main.py

Which outputs the file:

$ file dist/main/main
dist/main/main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=373ec5dee826653796e927ac3d65c9a8ec7db9da, stripped

Now, when I want to unpack it:

$ python pyinstxtractor.py dist/main/main
[*] Processing dist/main/main
[*] Error : Unsupported pyinstaller version or not a pyinstaller archive

I don't understand why the file cannot be unpacked while I've been looking through many posts telling that this should be possible and I'm beginning to doubt it.

Is the unpacking of the ELF file actually possible? Am I doing it the right away?

like image 563
Ra'Jiska Avatar asked Jun 28 '17 10:06

Ra'Jiska


2 Answers

According to the Github page, this script is applicable only for Windows binaries. There is an archive_viewer.py script distributed with pyinstaller itself that allows to view binary contents and extract it. If you get a .pyz file after extraction, use archive_viewer.py on it again. IIRC, after all you will get .pyc files, which have to be decompiled.

On my system (Manjaro Linux) I've found this script at /lib/python3.6/site-packages/PyInstaller/utils/cliutils

It is also available as pyi-archive_viewer (at /usr/bin/pyi-archive_viewer) after installing to global interpreter.

like image 185
bakatrouble Avatar answered Nov 15 '22 19:11

bakatrouble


Using pyi-archive_viewer CLI seems to be the supported solution, i.e. to print only the module names, recursively, and quit instead of prompting:

$ pyi-archive_viewer --log --recursive --brief build/PYZ-00.pyz
['__future__',
 '_aix_support',
---SNIP---
 'zipfile',
 'zipimport']

But if you don't want to parse or unsafely eval() the CLI output, it seems to work to use the library directly:

from PyInstaller.utils.cliutils import archive_viewer

archive = archive_viewer.get_archive('build/PYZ-00.pyz')
output = []
archive_viewer.get_content(archive, recursive=True, brief=True, output=output)
# Now, output is ['__future__', '_aix_support', ---SNIP--- 'zipfile', 'zipimport']

This use of the library is undocumented, but it's essentially the same to what the CLI does given those flags.

like image 31
Carl Walsh Avatar answered Nov 15 '22 19:11

Carl Walsh