Skip to main content

Make decompiling python code, generated from pyinstaller harder.

 General idea:

Pyinstaller when creates an executable generates .pyc files of the functions or scripts.

These .pyc files are easy to decompile.

So a better security option is to use .pyd files.

We need cython to generate .pyd files.

Read:

https://medium.com/analytics-vidhya/how-to-create-executable-of-your-python-application-from-linux-windows-mac-bcbcdd4603d4

https://programming.vip/docs/decompile-pyinstaller-packaged-exe-installation-package.html

https://github.com/extremecoders-re/pyinstxtractor/


Step 1: creating an executable .exe file.

Need: pyinstaller

pip install pyinstaller

then run:

pyinstaller yourfile.py

this will create an exe field in the dist directory - dist is the dir we are interested in not build

but in the dist dir there are supporting files as well,

to create a single executable file use:

pyinstaller yourfile.py --onefile

or 

pyinstaller -F simpleprogram.py


The problem:

This exe can be decompiled to view source code.


Decompiling:

https://github.com/extremecoders-re/pyinstxtractor/

python pyinstxtractor.py yourfile_single.exe


You will see yourfile_single.exe_extracted folder which has .pyc file of your original source code which can be decompiled - we are not doing that now but it can be decompiled. 

Read: https://programming.vip/docs/decompile-pyinstaller-packaged-exe-installation-package.html


Since .pyc file can be decompiled we are going to create a .pyd files for our functions

we create a separate file yourfile_support.py which contains the main code and yourfile.py which will import from yourfile_support.py and run the code, so yourfile.py doesn't do much but calls support file.

So first before compiling with pyinstaller we convert our yourfile_support.py to yourfile_support.py yourfile_support.pyd

when there are both .py and .pyd files in the folder, .pyd has preference over py and .pyd is difficult to decompile.


Creating .pyd

We need cython. Anaconda usually comes with cython but if you don't have install it.

Converting yourfile_support.py to yourfile_support.pyd:


first create another .py file named "build_pyd.py" having the following code:


# -*- coding: utf-8 -*-

"""

Created on Wed Aug 29 13:33:20 2018


@author: Li Zeng hai

"""


from distutils.core import setup

from Cython.Build import cythonize

 

setup(

  name = 'any words.....',

  ext_modules = cythonize(["yourfile_support.py",


                           

                           ]

  ),

)



Save it and then run:

python build_pyd.py build_ext --inplace

This will generate pyd file.


got error: error: Unable to find vcvarsall.bat

installed visual c++2015 build tools from:

http://go.microsoft.com/fwlink/?LinkId=691126&fixForIE=.exe.

worked!


It will generate something like simplefunction.cp37-win_amd64.pyd

rename it to simplefunction.pyd

delete all temp files and now do:

pyinstaller -F simpleprogram.py


Now do 

python pyinstxtractor.py yourfile_single.exe


now in the extracted folder you cannot see simplefunction.pyc

you can only see: simplefunction.pyd




--------------------- Best way that does all -------------

pyarmor

pip install pyarmor

we need pyinstaller preinstalled

pip install pyinstaller


Then just run

pyarmor pack --clean -e "--onefile " main.py

*the space after --onefile is intentional


sometimes pyinstaller will give recursion error - this is probably because the environment has a lot of files

so create an new anaconda enviornment, install only the required packages and run pyarmor - no errors


for gui apps:

pyarmor pack --clean -e "--onefile -w " main.py