How To Pack Obfuscated Scripts¶
The obfuscated scripts generated by PyArmor can replace Python scripts seamlessly, but there is an issue when packing them into one bundle by PyInstaller, py2exe, py2app, cx_Freeze:
All the dependencies of obfuscated scripts CAN NOT be found at all
To solve this problem, the common solution is
- Find all the dependenices by original scripts.
- Add runtimes files required by obfuscated scripts to the bundle
- Replace original scipts with obfuscated in the bundle
- Replace entry scrirpt with obfuscated one
PyArmor provides command pack to achieve this. But in some cases maybe it doesn’t work. This document describes what the command pack does, and also could be as a guide to bundle the obfuscated scripts by yourself.
Depend on what tool used, there are different ways.
First obfuscate scripts to dist/obf
:
pyarmor obfuscate --output dist/obf hello.py
Work with PyInstaller¶
Install pyinstaller
:
pip install pyinstaller
Generate specfile, add the obfuscated entry script and data files required by obfuscated scripts:
pyinstaller --add-data dist/obf/license.lic
--add-data dist/obf/pytransform.key
--add-data dist/obf/_pytransform.*
hello.py dist/obf/hello.py
Update specfile hello.spec
, insert the following lines after the
Analysis
object. The purpose is to replace all the original scripts with
obfuscated ones:
a.scripts[-1] = 'hello', r'dist/obf/hello.py', 'PYSOURCE'
for i in range(len(a.pure)):
if a.pure[i][1].startswith(a.pathex[0]):
x = a.pure[i][1].replace(a.pathex[0], os.path.normpath(os.path.abspath('dist/obf')))
if os.path.exists(x):
if hasattr(a.pure, '_code_cache'):
with open(x) as f:
a.pure._code_cache[a.pure[i][0]] = compile(f.read(), a.pure[i][1], 'exec')
a.pure[i] = a.pure[i][0], x, a.pure[i][2]
Run patched specfile to build final distribution:
pyinstaller --clean -y hello.spec
Note
Option –clean is required, otherwise the obfuscated scripts will not be replaced because the cached .pyz will be used.
Check obfuscated scripts work:
# It works
dist/hello/hello.exe
rm dist/hello/license.lic
# It should not work
dist/hello/hello.exe
Work with py2exe¶
For Python3.3 and later:
pip install py2exe
Build bundle executable to dist
with separated library:
build_exe --library library.zip hello.py
Build bundle executable with the obfuscated entry to dist/obf/dist
, all the
other obfuscated scripts should be include by -i name
or -p pkgname
:
( cd dist/obf;
build_exe --library library.zip -i queens hello.py )
Update dist/obf/library.zip
, which only includes the obfuscated scripts,
merge all the dependenices files from dist/library.zip
into it.
Copy all the files to final output:
cp -a dist/obf/dist/* dist/
Copy runtime files required by obfuscated scripts to finial output:
( cd dist/obf;
cp *.key *.lic _pytransform.dll ../dist/ )
Check obfuscated scripts work:
# It works
dist/hello.exe
rm dist/license.lic
# It should not work
dist/hello.exe
For Python2, write a setup.py
and run py2exe
as the following way:
python setup.py py2exe hello.py
Work with cx_Freeze 5¶
Install cx_Freeze
:
pip install cx_Freeze
Build bundle executable to dist
:
cxfreeze --target-dir=dist hello.py
Build bundle executable with the obfuscated entry to dist/obf/dist
, all the
other obfuscated scripts should be include by --include-modules NAMES
:
cd dist/obf
cxfreeze --target-dir=dist --include-modules=queens hello.py
Update dist/obf/python34.zip
, which only includes the obfuscated scripts,
merge all the dependenices files from dist/python34.zip
into it.
Copy all the files to final output:
cp -a dist/obf/dist/* dist/
Copy runtime files required by obfuscated scripts to finial output:
( cd dist/obf;
cp *.key *.lic _pytransform.dll ../dist/ )
Check obfuscated scripts work:
# It works
dist/hello.exe
rm dist/license.lic
# It should not work
dist/hello.exe