Contents
console
Pyarmor is a powerful tool to obfuscate Python scripts with rich option set that provides both high-level operations and full access to internals.
pyarmor
Syntax
pyarmor [options] <command> ...
Options
-h, --help show available command set then quit -v, --version show version information then quit -q, --silent suppress all normal output ... <-q>
-d, --debug show more information in the console ... <-d>
--home PATH set Pyarmor HOME path ... <--home>
These options can be used after pyarmor
but before command, here are available commands:
gen <pyarmor gen> |
Obfuscate scripts |
gen key <pyarmor gen key> |
Generate outer runtime key |
cfg <pyarmor cfg> |
Show and configure environments |
reg <pyarmor reg> |
Register Pyarmor |
See pyarmor <command> -h
for more information on a specific command.
Description
-q, --silent
Suppress all normal output.
For example:
pyarmor -q gen foo.py
-d, --debug
Show more information in the console
When something is wrong, print more debug informations in the console. For example:
pyarmor -d gen foo.py
--home PATH[,GLOBAL[,LOCAL[,REG]]]
Set Pyarmor Home Path
, Global Path
, Local Path
and registration file path
The default paths
Home Path
is~/.pyarmor/
Global Path
is~/.pyarmor/config/
Local Path
is./.pyarmor/
- registration file path is same as
Home Path
All of them could be changed by this option. For example, change home path to ~/.pyarmor2/
:
$ pyarmor --home ~/.pyarmor2 ...
Then
Global Path
is~/.pyarmor2/config/
- Registration files are stored in the
~/.pyarmor2/
Local Path
still is./.pyarmor/
Another example, keep all others but only change global path to ~/.pyarmor/config2/
:
$ pyarmor --home ,config2 ...
Another, keep all others but only change local path to /var/myproject
:
$ pyarmor --home ,,/var/myproject/ ...
Another, set registration file path to /opt/pyarmor/
:
$ pyarmor --home ,,,/opt/pyarmor ...
It's useful when may use sudo
to run pyarmor
occassionally. This makes sure the registration file could be found even switch to another user.
When there are many Pyarmor Licenses registerred in one machine, set each license to different registration file path. For example:
$ pyarmor --home ~/.pyarmor1 reg pyarmor-regfile-2051.zip
$ pyarmor --home ~/.pyarmor1 gen project1/foo.py
$ pyarmor --home ~/.pyarmor2 reg pyarmor-regfile-2052.zip
$ pyarmor --home ~/.pyarmor2 gen project2/foo.py
Start pyarmor with clean configuration by setting Global Path
and Local Path
to any non-exists path x
:
$ pyarmor --home ,x,x, gen foo.py
PYARMOR_HOME
Generate obfuscated scripts and all the required runtime files.
pyarmor gen
Syntax
pyarmor gen <options> <SCRIPT or PATH>
Options
-h, --help show option list and help information then quit -O PATH, --output PATH output path ... <-O>
-r, --recursive search scripts in recursive mode ... <-r>
-e DATE, --expired DATE set expired date ... <-e>
-b DEV, --bind-device DEV bind obfuscated scripts to device ... <-b>
--bind-data DATA store private data to runtime key ... <--bind-data>
--period N check runtime key periodically ... <--period>
--outer enable outer runtime key ... <--outer>
--platform NAME cross platform obfuscation ... <--platform>
-i store runtime files inside package ... <-i>
--prefix PREFIX import runtime package with PREFIX ... <--prefix>
--obf-module <0,1> obfuscate whole module (default is 1) ... <--obf-module>
--obf-code <0,1> obfuscate each function (default is 1) ... <--obf-code>
--no-wrap disable wrap mode ... <--no-wrap>
--enable <jit,rft,bcc,themida> enable different obfuscation features ... <--enable>
--mix-str protect string constant ... <--mix-str>
--private enable private mode for script ... <--private>
--restrict enable restrict mode for package ... <--restrict>
--assert-import assert module is obfuscated ... <--assert-import>
--assert-call assert function is obfuscated ... <--assert-call>
--pack BUNDLE repack bundle with obfuscated scripts ... <--pack>
Description
This command is designed to obfuscate all the scripts and packages in the command line. For example:
pyarmor gen foo.py
pyarmor gen foo.py goo.py koo.py
pyarmor gen src/mypkg
pyarmor gen src/pkg1 src/pkg2 libs/dbpkg
pyarmor gen -r src/mypkg
pyarmor gen -r main.py src/*.py libs/utils.py libs/dbpkg
All the files in the command line will be taken as Python script, because a few scripts has unknown extension but it's still Python script.
All the paths in the command line will be taken as Python Package, package name is set to path's basename, all the .py
files in this path are package modules. If this package has any sub-pacakge, use -r
to search recursively.
Do not use pyarmor gen src/*
to obfuscate a package, it will obfuscate any file in the src
, even they're not python scripts.
-O PATH, --output PATH
Set the output path for all the generated files, default is dist
-r, --recursive
When obfuscating package, search all scripts recursively. No this option, only the scripts in package path are obfuscated.
-i
When obfuscating package, store the runtime files inside package. For example:
$ pyarmor gen -r -i mypkg
The runtime package
will be stored inside package dist/mypkg
:
$ ls dist/
... mypkg/
$ ls dist/mypkg/
... pyarmor_runtime_000000/
Without this option, the output path is like this:
$ ls dist/
... mypkg/
... pyarmor_runtime_000000/
This option can't be used to obfuscate script.
--prefix PREFIX
Only used when obfuscating many packages at the same time and still store the runtime package inside package.
In this case, use this option to specify which package is used to store runtime package. For example:
$ pyarmor gen --prefix mypkg src/mypkg mypkg1 mypkg2
This command tells pyarmor to store runtime package inside dist/mypkg
, and make dist/mypkg1
and dist/mypkg2
to import runtime package from mypkg
.
Checking the content of .py
files in output path to make it clear.
As a comparison, obfuscating 3 packages without this option:
$ pyarmor gen -O dist2 src/mypkg mypkg1 mypkg2
And check .py
files in the path dist2
.
-e DATE, --expired DATE
Expired date of obfuscated scripts.
It supports 4 forms:
- A number stands for valid days
- A date with iso format
YYYY-MM-DD
- A leading
.
with above 2 forms
Without leading dot, the obfuscated scripts checks NTP server time. For example:
$ pyarmor gen -e 30 foo.py
$ pyarmor gen -e 2022-12-31 foo.py
With leading dot, it checks local time. For example:
$ pyarmor gen -e .30 foo.py
$ pyarmor gen -e .2022-12-31 foo.py
-b DEV, --bind-device DEV
Use this option multiple times to bind multiple machines
Bind obfuscated script to specified device. Now only harddisk serial number, ethernet address and IPv4 address are available.
For example:
$ pyarmor gen -b 128.16.4.10 foo.py
$ pyarmor gen -b 52:38:6a:f2:c2:ff foo.py
$ pyarmor gen -b HXS2000CN2A foo.py
Also set 30 valid days for this device:
$ pyarmor gen -e 30 -b 128.16.4.10 foo.py
Check all of hardware informations in this device:
$ pyarmor gen -b "128.16.4.10 52:38:6a:f2:c2:ff HXS2000CN2A" foo.py
Using this options multiple times means binding many machines. For example, the following command makes the obfuscated scripts could run 2 machiens:
$ pyarmor gen -b "52:38:6a:f2:c2:ff" -b "f8:ff:c2:27:00:7f" foo.py
In case there are more network cards, binding anyone by this form:
$ pyarmor gen -b "<2a:33:50:46:8f>" foo.py
Bind all network cards by this form:
$ pyarmor gen -b "<2a:33:50:46:8f,f0:28:69:c0:24:3a>" foo.py
In Linux, it's possible to bind named ethernet card:
$ pyarmor gen -b "eth1/fa:33:50:46:8f:3d" foo.py
If there are many harddisks. In Windows, binding anyone by sequence no:
$ pyarmor gen -b "/0:FV994730S6LLF07AY" foo.py
$ pyarmor gen -b "/1:KDX3298FS6P5AX380" foo.py
In Linux, binding to specify name:
$ pyarmor gen -b "/dev/vda2:KDX3298FS6P5AX380" foo.py
--bind-data DATA
DATA may be @FILENAME
or string
Store any private data to runtime key, then check it in the obfuscated scripts by yourself. It's mainly used with the hook script
to extend runtime key verification method.
If DATA has a leading @
, then the rest is a filename. Pyarmor reads the binary data from file, and store into runtime key.
For any other case, DATA is converted to bytes as private data.
--period N
Check Runtime Key
periodically.
Support units:
- s
- m
- h
The default unit is hour, for example, the following examples are equivalent:
$ pyarmor gen --period 1 foo.py
$ pyarmor gen --period 3600s foo.py
$ pyarmor gen --period 60m foo.py
$ pyarmor gen --period 1h foo.py
Note
If the obfuscated script enters an infinite loop without call any obfuscated function, it doesn't trigger periodic check.
--outer
Enable outer key
It tells the obfuscated scripts find runtime key
in outer file.
Once this option is specified, pyarmor gen key
must be used to generate an outer key file and copy to the corresponding path in target device
. Otherwise the obfuscated scripts will complain of missing license key to run the script
The default name of outer key is pyarmor.rkey
, it can be changed by this command:
$ pyarmor cfg outer_keyname=".pyarmor.key"
By this command the name of outer key is set to .pyarmor.key
.
--platform NAME
Specify target platform to run obfuscated scripts.
The name must be one of standard platform
defined by Pyarmor.
It requires pyarmor.cli.runtime
to get prebuilt binary libraries of other platforms.
--private
Enable private mode for scripts.
When private mode is enabled, the function name is empty in traceback. And the obfuscated scripts could not be imported by plain script or Python interpreter.
It can't be used with --restrict
, the latter enables private mode implicitly.
--restrict
Enable restirct mode for package, do not use it to obfuscate scripts.
It enables --private
implicitly, and has all the features of private mode.
When restrict mode is enabled, all the modules excpet __init__.py
in the package could not be imported by plain scripts.
For example, obfuscate a restrict package to dist/joker
:
$ pyarmor gen -i --restrict joker
$ ls dist/
... joker/
Then create a plaint script dist/foo.py
import joker
print('import joker should be OK')
from joker import queens
print('import joker.queens should fail')
Run it to verify:
$ cd dist
$ python foo.py
... import joker should be OK
... RuntimeError: unauthorized use of script
If there are extra modules need to be exported, list all the modules in this command:
$ pyarmor cfg exclude_restrict_modules="__init__ queens"
Then obfuscate the package again.
--obf-module <0,1>
Enable the whole module (default is 1)
--obf-code <0,1>
Enable each function in module (default is 1)
--no-wrap
Disable wrap mode
If wrap mode is enabled, when enter a function, it's restored. but when exit, this function will be obfuscated again.
If wrap mode is disabled, once the function is restored, it's never be obfuscated again.
If --obf-code
is 0
, this option is meaningless.
--enable <jit,rft,bcc,themida>
Enable different obfuscation features.
--enable-jit
Use JIT
to process some sentensive data to improve security.
--enable-rft
Enable RFT Mode
to obfuscate the script pro
--enable-bcc
Enable BCC Mode
to obfuscate the script pro
--enable-themida
Use Themida to protect extension module in runtime package
Only works for Windows platform.
--mix-str
Mix the string constant in scripts basic
--assert-call
Assert function is obfuscated
If this option is enabled, Pyarmor scans each function call in the scripts. If the called function is in the obfuscated scripts, protect it as below, and leave others as it is. For example,
def fib(n):
a, b = 0, 1
return a, b
print('hello')
fib(n)
will be changed to
def fib(n):
a, b = 0, 1
print('hello')
__assert_armored__(fib)(n)
The function __assert_armored__
is a builtin function in obfuscated script. It checks the argument, if it's an obfuscated function, then returns this function, otherwise raises protection exception.
In this example, fib
is protected, print
is not.
--assert-import
Assert module is obfuscated
If this option is enabled, Pyarmor scans each import
statement in the scripts. If the imported module is obfuscated, protect it as below, and leave others as it is. For example,
import sys
import foo
will be changed to
import sys
import foo
__assert_armored__(foo)
The function __assert_armored__
is a builtin function in obfuscated script. It checks the argument, if it's an obfuscated module, then return this module, otherwise raises protection exception.
This option neither touchs statement from import
, nor the module imported by function __import__
.
--pack BUNDLE
Repack bundle with obfuscated scripts
Here BUNDLE
is an executable file generated by PyInstaller
Pyarmor just obfuscates the script first.
Then unpack the bundle.
Next replace all the .pyc
in the bundle with obfuscated scripts, and append all the runtime files
to the bundle.
Finally repack the bundle and overwrite the original BUNDLE
.
Generate outer key
for obfuscated scripts.
pyarmor gen key
Syntax
pyarmor gen key <options>
Options
-O PATH, --output PATH output path -e DATE, --expired DATE set expired date --period N check runtime key periodically -b DEV, --bind-device DEV bind obfuscated scripts to device --bind-data store private data to runtime key
Description
This command is used to generate outer key
, the options in this command have same meaning as in the pyarmor gen
.
There must be at least one of option -e
or -b
for outer key
.
It's invalid that outer key is neither expired nor binding to a device. For this case, don't use outer key.
By default the outer key is saved to dist/pyarmor.rkey
. For example:
$ pyarmor gen key -e 30
$ ls dist/pyarmor.rkey
Save outer key to other path by this way:
$ pyarmor gen key -O dist/mykey2 -e 10
$ ls dist/mykey2/pyarmor.rkey
By default the outer key name is pyarmor.rkey
, use the following command to change outer key name to any others. For example, sky.lic
:
$ pyarmor cfg outer_keyname=sky.lic
$ pyarmor gen key -e 30
$ ls dist/sky.lic
Configure or show Pyarmor environments
pyarmor cfg
Syntax
pyarmor cfg <options> [OPT[=VALUE]] ...
Options
-h, --help show this help message and exit -p NAME private settings for special module or package -g, --global do everything in global settings, otherwise local settings -r, --reset reset option to default value --encoding ENCODING specify encoding to read configuration file
Description
Run this command without arguments to show all available options:
$ pyarmor cfg
Show one exact option obf_module
:
$ pyarmor cfg obf_module
Show all options which start with obf
:
$ pyarmor cfg obf*
Set option to int value by any of these forms:
$ pyarmor cfg obf_module 0
$ pyarmor cfg obf_module=0
$ pyarmor cfg obf_module =0
$ pyarmor cfg obf_module = 0
Set option to boolean value:
$ pyarmor cfg wrap_mode 0
$ pyarmor cfg wrap_mode=1
Set option to string value:
$ pyarmor cfg outer_keyname "sky.lic"
$ pyarmor cfg outer_keyname = "sky.lic"
Append word to an option. For example, pyexts
has 2 words .py .pyw
, append new one to it:
$ pyarmor cfg pyexts + ".pym"
Current settings
pyexts = .py .pyw .pym
Remove word from option:
$ pyarmor cfg pyexts - ".pym"
Current settings
pyexts = .py .pyw
Append new line to option:
$ pyarmor cfg rft_excludes ^ "/win.*/"
Current settings
rft_excludes = super
/win.*/
Reset option to default:
$ pyarmor cfg rft_excludes ""
$ pyarmor cfg rft_excludes=""
$ pyarmor cfg -r rft_excludes
Change option excludes
in the section finder
by this form:
$ pyarmor cfg finder:excludes "ast"
If no prefix finder
, for example:
$ pyarmor cfg excludes "ast"
Not only option excludes
in section finder
, but also in other sections assert.call
, mix.str
etc. are changed.
Sections
Section is group name of options, here are popular sections
- finder: how to search scripts
- builder: how to obfuscate scripts, main section
- runtime: how to generate runtime package and runtime key
These are not popular sections * mix.str: how to filter mix string * assert.call: how to filter assert function * assert.import: how to filter assert module * bcc: how to convert function to C code
-p NAME
Private settings for special module or package
All the settings is only used for specified module NAME.
-g, --global
Do everything in global settings
Without this option, all the changed settings are stored in Local Path
, generally it's ./.pyarmor/config
. By this option, everything is stored in Global Path
, generally it's ~/.pyarmor/config/global
-r, --reset
Reset option to default value
Register Pyarmor or upgrade Pyarmor license
pyarmor reg
Syntax
pyarmor reg [OPTIONS] [FILENAME]
Options
-h, --help show this help message and exit -p NAME, --product NAME license to this product -u, --upgrade upgrade Pyarmor license -g ID, --device ID device no. in group license
Arguments
The FILENAME
must be one of these forms:
pyarmor-regcode-xxxx.txt
got by purchasing Pyarmor licensepyarmor-regfile-xxxx.zip
got by initial registration with above file
Description
Check the registration information:
$ pyarmor -v
Initial registration
Initial registration by the following command, replace NAME
with real product name or non-profits
:
$ pyarmor reg -p NAME pyarmor-regcode-xxxx.txt
A registration file
pyarmor-regfile-xxxx.zip
will be generated after initial registration completed. Using this file for subsequent registration:
$ pyarmor reg pyarmor-regfile-xxxx.zip
Upgrading old license
Upgrading old license by the following command, if product name is not same as old license, it's ignored:
$ pyarmor reg -p NAME pyarmor-regcode-xxxx.txt
A registration file
pyarmor-regfile-xxxx.zip
will be generated after upgrade completed. Using this file for subsequent registration:
$ pyarmor reg pyarmor-regfile-xxxx.zip
Using group license
Pyarmor group
also need internet connect to initial registration, and generate the corresponding registration file
.
One group license could have 100 offline devices, each device has its own number, from 1 to 100.
For each device, first install Pyarmor 8.2+, and generate one device file. For example, run this command in device no. 1 to generate group device file pyarmor-group-device.1
:
$ pyarmor reg -g 1
Next prepare to generate device regfile pyarmor-device-regfile-xxxx.1.zip
for this device. It requires internet connection, group device file pyarmor-group-device.1
, group license registration file
.
For example, copy group device file to initial registration machine, save it to path .pyarmor/group/
, run the following command to generate pyarmor-device-regfile-xxxx.1.zip
:
$ mkdir -p .pyarmor/group
$ cp pyarmor-group-device.1 .pyarmor/group/
$ pyarmor reg -g 1 pyarmor-regfile-xxxx.zip
Copy device regfile to device no. 1, then run the following command:
$ pyarmor reg pyarmor-device-regfile-xxxx.1.zip
Repeat above steps for the rest device no. 2, no. 3 ...
-p NAME, --product NAME
Set product name bind to license
For non-commercial use, set product name to non-profits
When initial registration, use this option to set proudct name for this license.
It's meanless to use this option after initial registration.
TBD
is a special product name. If product name is TBD
at initial registration, the product name can be changed later.
For any other product name, it can't be changed any more.
Only Pyarmor basic
and Pyarmor pro
could set product name to TBD
-u, --upgrade
Upgrade old license to Pyarmor 8.0 Licese
Not all the old license could be upgrade to new license, check ../licenses
-g ID, --device ID
specify device no. in group license
Valid value is from 1 to 100
The following environment variables only used in Build Machine
when generating the obfuscated scripts, not in Target Device
.
PYARMOR_HOME
Same as pyarmor --home
It mainly used in the shell scrits to change Pyarmor settings. If pyarmor --home
is set, this environment var is ignored.
PYARMOR_PLATFORM
Set the right Platform
to run pyarmor
It's mainly used in some platforms Pyarmor could not tell right but still works.
PYARMOR_CC
Specify C compiler for bccmode
PYARMOR_CLI
Only for compatible with old Pyarmor, ignore this if you don't use old command prior to 8.0
If you do not use new commands in Pyarmor 8.0, and prefer to only use old commands, set it to 7
, for example:
# In Linux
export PYARMOR_CLI=7
pyarmor -h
# Or
PYARMOR_CLI=7 pyarmor -h
# In Windows
set PYARMOR_CLI=7
pyarmor -h
It forces command pyarmor
to use old cli directly.
Without it, pyarmor
first try new cli, if the command line couldn't be parsed by new cli, fallback to old cli.
This only works for command pyarmor
.