4.3. Insight Into Pack Command
Pyarmor 8.0 has no command pack, but --pack
. It could specify an executable file generated by PyInstaller:
pyinstaller foo.py
pyarmor gen --pack dist/foo/foo foo.py
If no options are set, pyarmor only obfuscates the scripts.
If this option is set, pyarmor first obfuscates the scripts, then does extra work:
Unpacking this executable to a temporary folder
Replacing the scripts in bundle with obfuscated ones
Appending runtime files to the bundle in this temporary folder
Repacking this temporary folder to an executable file and overwrite the old
Note that only list scripts are obfuscated, if need obfuscate more scripts and sub packages, list all of them in command line. For example:
pyarmor gen --pack dist/foo/foo -r *.py dir1 dir2 ...
In Darwin, let obfuscated scripts work in both intel and Apple Silicon by extra option ``–platform darwin.x86_64,darwin.arm64`:
pyarmor gen --pack dist/foo/foo --platform darwin.x86_64,darwin.arm64 foo.py
4.3.1. Packing obfuscated scripts manually
If something is wrong with --pack
, or the final bundle doesn’t work, try to pack the obfuscated scripts manually.
You need to know how to using PyInstaller and using spec file, if not, learn it by yourself.
Here is an example to pack script foo.py
in the path /path/to/src
First obfuscating the script by Pyarmor 1:
cd /path/to/src pyarmor gen -O obfdist -a foo.py
Moving runtime package to current path 2:
mv obfdist/pyarmor_runtime_000000 ./
Already have
foo.spec
, appending runtime package tohiddenimports
a = Analysis(
...
hiddenimports=['pyarmor_runtime_000000'],
...
)
Otherwise generating
foo.spec
by PyInstaller 3:pyi-makespec --hidden-import pyarmor_runtime_000000 foo.py
Patching
foo.spec
by inserting extra code aftera = Analysis
a = Analysis(
...
hiddenimports=['pyarmor_runtime_000000'],
...
)
# Pyarmor patch start:
def pyarmor_patcher(src, obfdist):
# Make sure both of them are absolute paths
src = os.path.abspath(src)
obfdist = os.path.abspath(obfdist)
count = 0
for i in range(len(a.scripts)):
if a.scripts[i][1].startswith(src):
x = a.scripts[i][1].replace(src, obfdist)
if os.path.exists(x):
a.scripts[i] = a.scripts[i][0], x, a.scripts[i][2]
count += 1
if count == 0:
raise RuntimeError('No obfuscated script found')
for i in range(len(a.pure)):
if a.pure[i][1].startswith(src):
x = a.pure[i][1].replace(src, obfdist)
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]
pyarmor_patcher(r'/path/to/src', r'/path/to/obfdist')
# Pyarmor patch end.
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
Generating final bundle by this patched
foo.spec
, also use option –clean to to remove all cached files:pyinstaller --clean foo.spec
If following this example, please
Replacing all the
/path/to/src
and/path/to/obfdist
with actual pathReplacing all the
pyarmor_runtime_000000
with actual name
how to verify obfuscated scripts have been packed
Inserting some print statements in the foo.spec
to print which script is replaced, or add some code only works in the obfuscated script.
For example, add one line in the main script foo.py
print('this is __pyarmor__', __pyarmor__)
If it’s not obfuscated, the final bundle will raise error.
notes
4.3.2. Segment fault in Apple M1
In Apple M1 if the final executable segment fault, please check codesign of runtime package:
$ codesign -v dist/foo/pyarmor_runtime_000000/pyarmor_runtime.so
And re-sign it if the code sign is invalid:
$ codesign -f -s dist/foo/pyarmor_runtime_000000/pyarmor_runtime.so
If you use --enable-bcc
or --enable-jit
to obfuscate the scripts, you need enable Allow Execution of JIT-compiled Code Entitlement
If your app doesn’t have the new signature format, or is missing the DER entitlements in the signature, you’ll need to re-sign the app on a Mac running macOS 11 or later, which includes the DER encoding by default.
If you’re unable to use macOS 11 or later to re-sign your app, you can re-sign it from the command-line in macOS 10.14 and later. To do so, use the following command to re-sign the MyApp.app app bundle with DER entitlements by using a signing identity named “Your Codesign Identity” stored in the keychain:
$ codesign -s "Your Codesign Identity" -f --preserve-metadata --generate-entitlement-der /path/to/MyApp.app