PyArmor is a command line tool used to obfuscate python scripts

PyArmor

PyArmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts. It protects Python scripts by the following ways:

  • Obfuscate code object to protect constants and literal strings.
  • Obfuscate co_code of each function (code object) in runtime.
  • Clear f_locals of frame as soon as code object completed execution.
  • Verify the license file of obfuscated scripts while running it.

Also refer to The Security of PyArmor

Support Platforms

  • Python 2.7 and Python3
  • Prebuilt Platform: win32, win_amd64, linux_i386, linux_x86_64, macosx_x86_64
  • Embedded Platform: Raspberry Pi, Banana Pi, Orange Pi, TS-4600 / TS-7600 and more

Refer to support platforms

Quick Start

Installation

pip install pyarmor

Obfuscate scripts

pyarmor obfuscate foo.py

Run obfuscated scripts

python dist/foo.py

Pack obfuscated scripts into one bundle

pip install pyinstaller
pyarmor pack foo.py

Obfuscate scripts with an expired license

pyarmor licenses --expired 2018-12-31 r001
pyarmor obfuscate --with-license licenses/r001/license.lic foo.py

There is also a web-ui package pyarmor-webui

pip install pyarmor-webui

Start webui, open web page in browser (snapshots)

pyarmor-webui

More usage, refer to

License & Purchase

PyArmor is published as shareware, free trial version never expires, but there are some limitations:

  • The trial version could not obfuscate the big scripts
  • The trial version uses same public capsule other than private capsule
  • The trial version could not download the latest dynamic library of extra platforms

For details, refer to PyArmor License.

Change Logs

It describes the fixed issues, new features, incompatible issues in different versions.

It's recommended to read this carefully before upgrading pyarmor.

Report issuses

If there is any question, first check these questions and solutions, it may help you solve the problem quickly.

If there is no solution, for technical issue, click here to report an issue according to the issue template, for business and security issue send email to [email protected].

Owner
Dashingsoft
Focus on how to obfuscate python scripts for more than ten years, Pyarmor has been a powerful tool in the field of protecting and distributing python scripts.
Dashingsoft
Comments
  • Access to raw code objects

    Access to raw code objects

    I obfuscated the following Python script.

    examples/test/mymod.py:

    from __future__ import division, absolute_import, print_function, unicode_literals
    
    def func2():
        print('func2')
    
    def func3():
        print(err)
    

    Build pyarmor:

    python pyarmor.py init --src=examples/test --entry=mymod.py projects/test
    
    python pyarmor.py config --disable-restrict-mode=1 projects/test
    
    cd projects/test
    ./pyarmor build
    

    In Python shell:

    >>> import mymod, dis
    >>> dis.dis(mymod)
    Disassembly of func2:
      4     >>    0 LOAD_GLOBAL              0 (print)
                  3 LOAD_CONST               1 (u'func2')
                  6 CALL_FUNCTION            1
                  9 POP_TOP             
                 10 LOAD_CONST               0 (None)
                 13 RETURN_VALUE        
                 14 NOP                 
                 15 NOP                 
                 16 NOP                 
                 17 NOP                 
                 18 NOP                 
                 19 NOP                 
                 20 NOP                 
                 21 NOP                 
                 22 NOP                 
                 23 NOP                 
                 24 JUMP_ABSOLUTE            0
    
    Disassembly of func3:
      7     >>    0 LOAD_GLOBAL              0 (print)
                  3 LOAD_GLOBAL              1 (err)
                  6 CALL_FUNCTION            1
                  9 POP_TOP             
                 10 LOAD_CONST               0 (None)
                 13 RETURN_VALUE        
                 14 NOP                 
                 15 NOP                 
                 16 NOP                 
                 17 NOP                 
                 18 NOP                 
                 19 NOP                 
                 20 NOP                 
                 21 NOP                 
                 22 NOP                 
                 23 NOP                 
                 24 JUMP_ABSOLUTE            0
    

    Is it the correct behaviour that you have access to the raw code objects of a module? So, what is the advantage of using pyarmor? Thanks.

  • Pyarmor是否可以对第三方工具supervisor的py源码程序加密?

    Pyarmor是否可以对第三方工具supervisor的py源码程序加密?

    您好!Pyarmor是否可以对第三方工具supervisor的py源码程序加密?我对supervisor的py源码程序进行加密,suservisorctl.py 执行完后报堆栈溢出错误。以下我的报错信息!

    *** Error in `python': corrupted double-linked list: 0x0000000001ee32f0 *** ======= Backtrace: ========= /lib64/libc.so.6(+0x7f3e4)[0x7f0b7fc0b3e4] /lib64/libc.so.6(+0x8132d)[0x7f0b7fc0d32d] /lib64/libpython2.7.so.1.0(+0x817d8)[0x7f0b809007d8] /lib64/libpython2.7.so.1.0(+0x817bf)[0x7f0b809007bf] /lib64/libpython2.7.so.1.0(+0x59c7b)[0x7f0b808d8c7b] /lib64/libpython2.7.so.1.0(+0x817bf)[0x7f0b809007bf] /lib64/libpython2.7.so.1.0(+0x9e254)[0x7f0b8091d254] /lib64/libpython2.7.so.1.0(+0x817bf)[0x7f0b809007bf] /lib64/libpython2.7.so.1.0(+0x817bf)[0x7f0b809007bf] /lib64/libpython2.7.so.1.0(+0x9e254)[0x7f0b8091d254] /lib64/libpython2.7.so.1.0(+0x808df)[0x7f0b808ff8df] /lib64/libpython2.7.so.1.0(+0x822a0)[0x7f0b809012a0] /lib64/libpython2.7.so.1.0(_PyModule_Clear+0x16c)[0x7f0b80905dac] /lib64/libpython2.7.so.1.0(PyImport_Cleanup+0x27f)[0x7f0b80975d3f] /lib64/libpython2.7.so.1.0(Py_Finalize+0xfe)[0x7f0b809817ee] /lib64/libpython2.7.so.1.0(Py_Main+0x6a5)[0x7f0b80992ba5] /lib64/libc.so.6(__libc_start_main+0xf5)[0x7f0b7fbae555] python[0x40068e] ======= Memory map: ======== 00400000-00401000 r-xp 00000000 08:08 756171 /usr/bin/python2.7 00600000-00601000 r--p 00000000 08:08 756171 /usr/bin/python2.7 00601000-00602000 rw-p 00001000 08:08 756171 /usr/bin/python2.7 01a69000-01fc3000 rw-p 00000000 00:00 0 [heap] 7f0b6c000000-7f0b6c021000 rw-p 00000000 00:00 0 7f0b6c021000-7f0b70000000 ---p 00000000 00:00 0 7f0b72ce8000-7f0b72cfd000 r-xp 00000000 08:08 757853 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 7f0b72cfd000-7f0b72efc000 ---p 00015000 08:08 757853 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 7f0b72efc000-7f0b72efd000 r--p 00014000 08:08 757853 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 7f0b72efd000-7f0b72efe000 rw-p 00015000 08:08 757853 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 7f0b72efe000-7f0b72f0a000 r-xp 00000000 08:08 758866 /usr/lib64/libnss_files-2.17.so 7f0b72f0a000-7f0b73109000 ---p 0000c000 08:08 758866 /usr/lib64/libnss_files-2.17.so 7f0b73109000-7f0b7310a000 r--p 0000b000 08:08 758866 /usr/lib64/libnss_files-2.17.so 7f0b7310a000-7f0b7310b000 rw-p 0000c000 08:08 758866 /usr/lib64/libnss_files-2.17.so 7f0b7310b000-7f0b731d1000 rw-p 00000000 00:00 0 7f0b731d1000-7f0b731d3000 r-xp 00000000 08:08 804984 /usr/lib64/python2.7/lib-dynload/syslog.so 7f0b731d3000-7f0b733d2000 ---p 00002000 08:08 804984 /usr/lib64/python2.7/lib-dynload/syslog.so 7f0b733d2000-7f0b733d3000 r--p 00001000 08:08 804984 /usr/lib64/python2.7/lib-dynload/syslog.so 7f0b733d3000-7f0b733d4000 rw-p 00002000 08:08 804984 /usr/lib64/python2.7/lib-dynload/syslog.so 7f0b733d4000-7f0b733d6000 r-xp 00000000 08:08 804903 /usr/lib64/python2.7/lib-dynload/resource.so 7f0b733d6000-7f0b735d5000 ---p 00002000 08:08 804903 /usr/lib64/python2.7/lib-dynload/resource.so 7f0b735d5000-7f0b735d6000 r--p 00001000 08:08 804903 /usr/lib64/python2.7/lib-dynload/resource.so 7f0b735d6000-7f0b735d7000 rw-p 00002000 08:08 804903 /usr/lib64/python2.7/lib-dynload/resource.so 7f0b735d7000-7f0b735dc000 r-xp 00000000 08:08 804904 /usr/lib64/python2.7/lib-dynload/selectmodule.so 7f0b735dc000-7f0b737db000 ---p 00005000 08:08 804904 /usr/lib64/python2.7/lib-dynload/selectmodule.so 7f0b737db000-7f0b737dc000 r--p 00004000 08:08 804904 /usr/lib64/python2.7/lib-dynload/selectmodule.so 7f0b737dc000-7f0b737de000 rw-p 00005000 08:08 804904 /usr/lib64/python2.7/lib-dynload/selectmodule.so 7f0b737de000-7f0b73b5e000 rw-p 00000000 00:00 0 7f0b73b5e000-7f0b73b62000 r-xp 00000000 08:08 804535 /usr/lib64/python2.7/lib-dynload/_localemodule.so 7f0b73b62000-7f0b73d61000 ---p 00004000 08:08 804535 /usr/lib64/python2.7/lib-dynload/_localemodule.so 7f0b73d61000-7f0b73d62000 r--p 00003000 08:08 804535 /usr/lib64/python2.7/lib-dynload/_localemodule.so 7f0b73d62000-7f0b73d63000 rw-p 00004000 08:08 804535 /usr/lib64/python2.7/lib-dynload/_localemodule.so 7f0b73d63000-7f0b73e23000 rw-p 00000000 00:00 0 7f0b73e23000-7f0b73e25000 r-xp 00000000 08:08 804664 /usr/lib64/python2.7/lib-dynload/grpmodule.so 7f0b73e25000-7f0b74024000 ---p 00002000 08:08 804664 /usr/lib64/python2.7/lib-dynload/grpmodule.so 7f0b74024000-7f0b74025000 r--p 00001000 08:08 804664 /usr/lib64/python2.7/lib-dynload/grpmodule.so 7f0b74025000-7f0b74026000 rw-p 00002000 08:08 804664 /usr/lib64/python2.7/lib-dynload/grpmodule.so 7f0b74026000-7f0b74066000 rw-p 00000000 00:00 0 7f0b74066000-7f0b7408d000 r-xp 00000000 08:08 754673 /usr/lib64/libexpat.so.1.6.0 7f0b7408d000-7f0b7428d000 ---p 00027000 08:08 754673 /usr/lib64/libexpat.so.1.6.0 7f0b7428d000-7f0b7428f000 r--p 00027000 08:08 754673 /usr/lib64/libexpat.so.1.6.0 7f0b7428f000-7f0b74290000 rw-p 00029000 08:08 754673 /usr/lib64/libexpat.so.1.6.0 7f0b74290000-7f0b7429b000 r-xp 00000000 08:08 803410 /usr/lib64/python2.7/lib-dynload/pyexpat.so 7f0b7429b000-7f0b7449a000 ---p 0000b000 08:08 803410 /usr/lib64/python2.7/lib-dynload/pyexpat.so 7f0b7449a000-7f0b7449b000 r--p 0000a000 08:08 803410 /usr/lib64/python2.7/lib-dynload/pyexpat.so 7f0b7449b000-7f0b7449d000 rw-p 0000b000 08:08 803410 /usr/lib64/python2.7/lib-dynload/pyexpat.so 7f0b7449d000-7f0b744ae000 r-xp 00000000 08:08 804584 /usr/lib64/python2.7/lib-dynload/datetime.so 7f0b744ae000-7f0b746ad000 ---p 00011000 08:08 804584 /usr/lib64/python2.7/lib-dynload/datetime.so 7f0b746ad000-7f0b746ae000 r--p 00010000 08:08 804584 /usr/lib64/python2.7/lib-dynload/datetime.so 7f0b746ae000-7f0b746b2000 rw-p 00011000 08:08 804584 /usr/lib64/python2.7/lib-dynload/datetime.so 7f0b746b2000-7f0b746b6000 r-xp 00000000 08:08 805277 /usr/lib64/python2.7/lib-dynload/zlibmodule.so 7f0b746b6000-7f0b748b5000 ---p 00004000 08:08 805277 /usr/lib64/python2.7/lib-dynload/zlibmodule.so 7f0b748b5000-7f0b748b6000 r--p 00003000 08:08 805277 /usr/lib64/python2.7/lib-dynload/zlibmodule.so

  • Restrict Mode Examples?

    Restrict Mode Examples?

    Hi @jondy,

    I know your pretty busy resolving the issues that came about with 6.3.0, I was just wondering if i could get some clear proper examples of how to use the restrict modes..

    What im trying to do

    if i have a dir

    __init__.py
    packer.py
    

    I want __init__.py to be import-able with restrict 1, but how do i then also have packer.py restrict 3 so it cant be imported outside of the __init__.py?

    You doc doesn't cover proper examples things like this, it just doesn't make it clear enough , sorry

  • Issue with the pytransform and NameError:  '__pyarmor__'

    Issue with the pytransform and NameError: '__pyarmor__'

    Hello,

    Firstly, I should appreciate the work that you have put in here. It's pretty cool. It works great, however, I have some concerns for this package to use in some usual cases.

    1. This package works pretty good, If you want to secure a single python file, which again is not a usual case out in the production or in normal cases.
    2. If I tend to try the obfuscation on the python executables in a folder, one among all the files present in the folder work well, but the others throw NameError: name '__pyarmor__' is not defined, as they miss bootstrap-code. This is concerning.
    3. If I use pyarmor obfuscation on the python libraries as well as the executable, It turns out with the error : exception: _pytransform can not be loaded twice. Usually, It is equally important to secure both the libraries and its executable in python. Libraries are the place where you have most of the important info is present.
    4. So, It is likely impossible to completely secure the complete python package, such as below:
    packagename
     |- src/
        |- packagename/
          |- __init__.py
          |- yourfiles.py
     |- scripts/
        |- non-exported python files
    
    1. Moreover, the files that get generated when you obfuscate the code, _pytransform.so license.lic pytransform.key pytransform.py. These files are pretty much similar in most of the case, irrespective of the file you use to obfuscate, so why not to have them in a library, so that you don't need to have a huge duplication in the case of the packages with the libraries as above.

    Let me know your view on this, Thank you.

  • Can't build a working exe when using super mode

    Can't build a working exe when using super mode

    • Happens only when we use super mode to obfuscate the project, when built with advanced 0 the obfuscated and packaged code works without any issue.
    • Packaged with pyinstaller (not pyarmor pack), spec file is changed to include different pytransform generated by super mode Datas = [('pytransform.pyd','.')...]

    Not sure how I can get more info that would be useful to find the issue, any ideas ?

    {
      "version": "2.0",
      "name": "Prod super mode build",
      "title": "Prod super mode build",
      "src": ".",
      "is_package": null,
      "manifest": "global-include *.py",
      "entry": "main.py",
      "output": "dist",
      "runtime_path": null,
      "restrict_mode": 2,
      "obf_code": 2,
      "obf_mod": 1,
      "wrap_mode": 1,
      "advanced_mode": 2,
      "bootstrap_code": 1,
      "cross_protection": 0,
      "plugins": null,
      "platform": "windows.x86_64.11.py37",
      "package_runtime": 1,
      "enable_suffix": 0,
      "license_file": null,
      "build_time": 1595425907.0985913
    }
    

    Debug

    Microsoft Windows [Version 10.0.18362.959]
    (c) 2019 Microsoft Corporation. Alle rechten voorbehouden.
    
    C:\Users\user\Desktop\O Prod super mode build\dist\dist>"C:\Users\user\Desktop\O Prod super mode build\dist\dist\OAIO V1.1.2.exe"
    [21812] PyInstaller Bootloader 3.x
    [21812] LOADER: executable is C:\Users\user\Desktop\O Prod super mode build\dist\dist\OAIO V1.1.2.exe
    [21812] LOADER: homepath is C:\Users\user\Desktop\O Prod super mode build\dist\dist
    [21812] LOADER: _MEIPASS2 is NULL
    [21812] LOADER: archivename is C:\Users\user\Desktop\O Prod super mode build\dist\dist\OAIO V1.1.2.exe
    [21812] LOADER: Extracting binaries
    [21812] LOADER: Executing self as child
    [21812] LOADER: set _MEIPASS2 to C:\Users\user\AppData\Local\Temp\_MEI218122
    [21812] LOADER: Setting up to run child
    [21812] LOADER: Creating child process
    [21812] LOADER: Waiting for child process to finish...
    [26280] PyInstaller Bootloader 3.x
    [26280] LOADER: executable is C:\Users\user\Desktop\O Prod super mode build\dist\dist\OAIO V1.1.2.exe
    [26280] LOADER: homepath is C:\Users\user\Desktop\O Prod super mode build\dist\dist
    [26280] LOADER: _MEIPASS2 is C:\Users\user\AppData\Local\Temp\_MEI218122
    [26280] LOADER: archivename is C:\Users\user\Desktop\O Prod super mode build\dist\dist\OAIO V1.1.2.exe
    [26280] LOADER: SetDllDirectory(C:\Users\user\AppData\Local\Temp\_MEI218122)
    [26280] LOADER: Already in the child - running user's code.
    [26280] LOADER: manifestpath: C:\Users\user\AppData\Local\Temp\_MEI218122\OAIO V1.1.2.exe.manifest
    [26280] LOADER: Error activating the context: ActivateActCtx:
    An attempt to set the default context for activating a process failed because it has already been set.
    
    [26280] LOADER: Python library: C:\Users\user\AppData\Local\Temp\_MEI218122\python37.dll
    [26280] LOADER: Loaded functions from Python library.
    [26280] LOADER: Manipulating environment (sys.path, sys.prefix)
    [26280] LOADER: sys.prefix is C:\Users\user\AppData\Local\Temp\_MEI218122
    [26280] LOADER: Pre-init sys.path is C:\Users\user\AppData\Local\Temp\_MEI218122\base_library.zip;C:\Users\user\AppData\Local\Temp\_MEI218122
    [26280] LOADER: Setting runtime options
    [26280] LOADER: Bootloader option: pyi-windows-manifest-filename OAIO V1.1.2.exe.manifest
    [26280] LOADER: Initializing python
    [26280] LOADER: Overriding Python's sys.path
    [26280] LOADER: Post-init sys.path is C:\Users\user\AppData\Local\Temp\_MEI218122\base_library.zip;C:\Users\user\AppData\Local\Temp\_MEI218122
    [26280] LOADER: Setting sys.argv
    [26280] LOADER: setting sys._MEIPASS
    [26280] LOADER: importing modules from CArchive
    [26280] LOADER: extracted struct
    [26280] LOADER: callfunction returned...
    [26280] LOADER: extracted pyimod01_os_path
    [26280] LOADER: callfunction returned...
    [26280] LOADER: extracted pyimod02_archive
    [26280] LOADER: callfunction returned...
    [26280] LOADER: extracted pyimod03_importers
    [26280] LOADER: callfunction returned...
    [26280] LOADER: Installing PYZ archive with Python modules.
    [26280] LOADER: PYZ archive: PYZ-00.pyz
    [26280] LOADER: Running pyiboot01_bootstrap.py
    [26280] LOADER: Running pyi_rth_multiprocessing.py
    [26280] LOADER: Running pyi_rth__tkinter.py
    [26280] LOADER: Running pyi_rth_pkgres.py
    [26280] LOADER: Running pyi_rth_pyqt5webengine.py
    [26280] LOADER: Running pyi_rth_pyqt5.py
    [26280] LOADER: Running pyi_rth_certifi.py
    [26280] LOADER: Running pyi_rth_win32comgenpy.py
    [26280] LOADER: Running Main.py
    [21812] LOADER: Back to parent (RC: -1073741571)
    [21812] LOADER: Doing cleanup
    [21812] LOADER: Freeing archive status for C:\Users\user\Desktop\O Prod super mode build\dist\dist\OAIO V1.1.2.exe
    
  •  Pack command, causes unknown behaviour of the app

    Pack command, causes unknown behaviour of the app

    Using the following commands to pack our applciation. pyarmor init --entry "MRT.py,MRTFiles/attack_controller.py,MRTFiles/attack_dict.py,MRTFiles/cleanup.py,MRTFiles/play.py,MRTFiles/player.py,MRTFiles/vcspam.py,MRTFiles/ServerSmasher/serversmasher.py,MRTFiles/ServerSmasher/serversmasherGUI.py,MRTFiles/ServerSmasher/smconfig.py,plugins/Ghost Ping.py,plugins/helper.py,plugins/Additional/ghostpingmenu.py"

    pyarmor pack -e " --clean -F -p MRTFiles -p plugins --noupx --onefile" .

    Note, that in MRT.py, there are calls, that will start a python file located in the MRTFiles folder(subprocess.popen(executeable, "./MRTFiles/attack_controller", ...)

    The main app does start but once I start a feature it will just start the main application again.

  • Is there any difference in obfuscation between trial version and license registration?

    Is there any difference in obfuscation between trial version and license registration?

    Hello :)

    I am using pyarmor 6.8.1 version.

    After obfuscation in the TRIAL version, the service starts normally when applied to uwsgi, but if you register a license and proceed with obfuscation, the uwsgi service will not start normally.

    The same is true if you delete the licensed pyarmor directory and re-register the license as described in the guide.

    Is there a part that needs to be set differently from the trial version when registering a license?

    For your information, no additional error message is captured in the log.

  • Advanced mode 1 Failing with Pyenv environment on Pyarmor(6.2.1)

    Advanced mode 1 Failing with Pyenv environment on Pyarmor(6.2.1)

    Hi Again,

    Environment

    Python - 3.6.9 OS - Ubuntu 20.04 Pyarmor - 6.2.0

    Project structure

    mypkg ├── bar.py ├── foo.py └── init.py

    Configuration files

    I am using the child project structure to demonstrate a use-case for a large package. Here we are just obfuscating everything else with restrict mode 4 and using restrict mode 1 for __init__.py. As is recommended for a package.

    # Content .pyarmor_config
    { 
      "version": "2.0",
      "name": "mypkg",
      "title": "mypkg",
      "src": ".",
      "is_package": 1,
      "manifest": "include __init__.py",
      "entry": "__init__.py",
      "output": "dist",
      "runtime_path": null,
      "restrict_mode": 1,
      "obf_code": 2,
      "obf_mod": 1,
      "wrap_mode": 1,
      "advanced_mode": 0,
      "bootstrap_code": 1,
      "cross_protection": 1,
      "plugins": null,
      "platform": null,
      "package_runtime": 1,
      "enable_suffix": 0,
      "license_file": null,
      "build_time": 1589994512.6738808
    }
    
    # Content .pyarmor_config_pkg
    {
      "version": "2.0",
      "name": "mypkg",
      "title": "mypkg",
      "src": ".",
      "is_package": 1,
      "manifest": "global-include *.py, exclude __init__.py",
      "entry": "",
      "output": "dist",
      "runtime_path": null,
      "restrict_mode": 4,
      "obf_code": 2,
      "obf_mod": 1,
      "wrap_mode": 1,
      "advanced_mode": 0,
      "bootstrap_code": 1,
      "cross_protection": 1,
      "plugins": null,
      "platform": null,
      "package_runtime": 1,
      "enable_suffix": 0,
      "license_file": null,
      "build_time": 1589994515.6668053
    }
    

    Command :

    pyarmor build -B
    pyarmor build --no-runtime -B .pyarmor_config_pkg
    

    The build completes successfully.

    Behaviour/Expectation

    If we try to import the obfuscated mykg then we get the following error

    Python 3.6.9 (default, May 20 2020, 20:21:06) 
    [GCC 9.3.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import mypkg
    XXX lineno: 8, opcode: 228
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "</media/e0lithic/D/GameX/pyarmor_test/mypkg/dist/mypkg/__init__.py>", line 3, in <module>
      File "<frozen mypkg>", line 8, in <module>
    SystemError: unknown opcode
    

    If we just turn advanced_mode 0 in both configuration files and rerun the build. I am able to import the package.

    I read the documentation but the python 3.6 limitation was only mentioned for advanced_mode 2 / a.k.a super mode. Is the support for advanced mode 1 on python 3.6 also depreciated? Kindly let me know if I am missing something.

    Thanks

  • [Query/Bug] Getting failures in project when using restrict mode 3

    [Query/Bug] Getting failures in project when using restrict mode 3

    HI,

    First of all I would like to thank you for the brilliant work you have done. Kudos!

    Configuration

    INFO     PyArmor Version 5.9.6
    INFO     Project  information
                   version: 2.0
                      name: encrypted_backend
                     title: encrypted_backend
                       src: ../backend
                is_package: None
                  manifest: global-include *.py
                     entry: manage.py
                    output: .
              runtime_path: None
             restrict_mode: 3
                  obf_code: 1
                   obf_mod: 1
                 wrap_mode: 1
             advanced_mode: 1
            bootstrap_code: 1
          cross_protection: 1
                   plugins: None
                  platform: None
           package_runtime: 1
             enable_suffix: 0
              license_file: None
                build_time: Mon Apr 13 14:24:03 2020
    

    Expectation

    • The project has multiple packages and sub packages. However intent is to obfuscate all under one umbrella, hence using a single recursive build.
    • The project being a django backend, has an entry script manage.py, which is only supposed to be executed and not imported anywhere. As such restrict mode 3 seemed to be an ideal fit.

    Error

    • The project obfuscates successfully, however, I get random failures when i try to execute it. Errors like the following - Pytransform Error: This function could not be called from the plain script when running < frozen x.y.z >

    My understanding is that since all the functions are being called from obfuscated files, the error should not pop up. I did some hit and trials in the x.y.z file path and it appears that commenting code like the following makes the error go away (doesn't make sense!).

    if not os.path.exists(root):
            os.makedirs(root)
    if not os.path.exists(dir_path):
            os.makedirs(dir_path)
    

    But then it pops up somewhere in other file. Considering the sheer size of the project and not knowing the underlying code for pyarmor, I am unable to create a directed reproducible example for you unfortunately. Please let me know if I am missing something, or any heads up so that I can provide you with a better reproducible example.

    PS - I am able to successfully run the project with restrict mode 1 and 2.

    Thanks.

  • Target platform string ['linux.x86_64.11.py37'] being read as a list of characters

    Target platform string ['linux.x86_64.11.py37'] being read as a list of characters

    I am using this method https://pyarmor.readthedocs.io/en/latest/advanced.html#distributing-obfuscated-package-with-pip

    My script for obsfucation, run from project/shell directory:

    #!/usr/bin/env bash
    # Prepare the obsfucation, run from shell directory
    rm -rf ../obsfucated
    mkdir -p ../obsfucated
    pyarmor  runtime -O obsfucated --enable-suffix 1 --advanced 2
    pyarmor obfuscate  -r --with-runtime @obsfucated  --exclude package.py,setu*.py,test,test_data,dist,build ../
    

    I am having this issue with the approach

    l$ /bin/bash /home/david/projects/product/shell/obsfucate.sh
    INFO     PyArmor Version 6.5.5
    INFO     Update target platforms to: ['linux.x86_64.11.py37']
    INFO     Generating super runtime library to obsfucated
    INFO     Extract pytransform.key
    INFO     Generate default license file
    INFO     Copying /home/david/.pyarmor/platforms/linux/x86_64/11/py37/pytransform.cpython-37m-x86_64-linux-gnu.so
    INFO     Rename extension to pytransform_vax_000925.cpython-37m-x86_64-linux-gnu.so
    INFO     Patch extension obsfucated/pytransform_vax_000925.cpython-37m-x86_64-linux-gnu.so
    INFO     Patch library file OK
    INFO     Generate runtime files OK
    INFO     Generating protection script ...
    INFO     Generating bootstrap script ...
    INFO     Generating bootstrap script obsfucated/pytransform_bootstrap.py OK
    INFO     PyArmor Version 6.5.5
    INFO     Got settings from --runtime: obsfucated
    INFO         Platforms: linux.x86_64.11.py37
    INFO         Advanced: 2
    INFO         Suffix: _vax_000925
    INFO         License: embedded
    INFO     Target platforms: ['l', 'i', 'n', 'u', 'x', '.', 'x', '8', '6', '_', '6', '4', '.', '1', '1', '.', 'p', 'y', '3', '7']
    ERROR    No available dynamic library for l with features ['11']
    

    Why is it detecting my Target platform and reading it as an array rather than a string?

  • Super-Mode and Threading

    Super-Mode and Threading

    If you thread with 2 or more children under super-mode (advanced 2) it causes python to segfault, I had users complaining so I tested

    • unencrypted - fine
    • advanced mode 1 (default) - fine
    • advanced mode 2 (super-mode) - segfault

    This appears to happen on windows, linux and osx under python 3.7 and 3.8

    right before the segfault you can see it trying to open pytransform...

    30072 stat("/tmp/QQ/dist/helheim/pytransform.cpython-37m-x86_64-linux-gnu.so", {st_dev=makedev(0x8, 0x1), st_ino=4316040, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=1400, st_size=711888, st_atime=1592127252 /* 2020-06-14T21:34:12.009638613+1200 */, st_atime_nsec=9638613, st_mtim
    e=1592123947 /* 2020-06-14T20:39:07+1200 */, st_mtime_nsec=0, st_ctime=1592127203 /* 2020-06-14T21:33:23.342523653+1200 */, st_ctime_nsec=342523653}) = 0
    30072 openat(AT_FDCWD, "/tmp/QQ/dist/helheim/pytransform.cpython-37m-x86_64-linux-gnu.so", O_RDONLY|O_CLOEXEC) = 4
    30072 read(4, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\356\0\0\0\0\0\[email protected]\0\0\0\0\0\0\0\20\326\n\0\0\0\0\0\0\0\0\[email protected]\08\0\7\[email protected]\0\33\0\32\0\1\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\254\204\n\0\0\0\0\0\254\204\n\0\0\0\0\0\0\0 \0\0\0\0\0\1\0\0\0\6\0\0\0(\216\n\0\0\0\0\0(\216*\0\0\0\0\0(\2
    16*\0\0\0\0\0\310F\0\0\0\0\0\0h\216\0\0\0\0\0\0\0\0 \0\0\0\0\0\2\0\0\0\6\0\0\0\350\233\n\0\0\0\0\0\350\233*\0\0\0\0\0\350\233*\0\0\0\0\0\320\1\0\0\0\0\0\0\320\1\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0\310\1\0\0\0\0\0\0\310\1\0\0\0\0\0\0\310\1\0\0\0\0\0\0$\0\0\0\0\0\0\0$\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0P\345td\4\0\
    0\0\374\336\t\0\0\0\0\0\374\336\t\0\0\0\0\0\374\336\t\0\0\0\0\0t\25\0\0\0\0\0\0t\25\0\0\0\0\0\0\4\0\0\0\0\0\0\0Q\345td\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0R\345td\4\0\0\0(\216\n\0\0\0\0\0(\216*\0\0\0\0\0(\216*\0\0\0\0\0\330\21\0\0\0\0\0\0\330\21\0\0
    \0\0\0\0\1\0\0\0\0\0\0\0\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\207w`\266\231Jn\\\342\304\270u\0?/1P\256!w\0\0\0\0\7\1\0\0\7\1\0\0 \0\0\0\v\0\0\0\201\f\0\202\[email protected]\222\260\21\200$\1T!\4\10!\10\250\[email protected]#\200>8\244\211\354\200x\304\25&\0\4J\30D\255\n\f\26\1!\30\0c\0,\4D\201P\30\\\374]\305\4\1H\314S\0\221\260 \[email protected]\240D \3\2$ !$\24
    2\10QE\201\201\201J\10\211\10\5\2`\302P\343(B\4\22Q\t\24\220A\200\4|\240\272\212%-\[email protected]\225\203\210\250\236\4\1\0\252\210\4\2,\360\246<\252h4\222\[email protected]@\10\r\t\311\310 \1Q\340\234A&\2616\200\0\200A`.\202\200\24\0\220\0\30\6\2\22\30\21\20\0\1\1\2(\20\0\1 \200$\2\263\2055\\\2\20\7\322\36\221D\0\10\2\10\2\200\200\n\0\1\30
    0\0100\242X\1\3h\320\262\310!D\220\204)P\342\304\243E\5\20\20\16\0\200`\235\202\0100\"\31 \301\312\2\2\2\5\0\24 \0\210\210\240\[email protected]\4\7\1\0\0\10\1\0\0\t\1\0\0\n\1\0\0\20\1\0\0\0\0\0\0\0\0\0\0\21\1\0\0\23\1\0\0\0\0\0\0\25\1\0\0\27\1\0\0\0\0\0\0\32\1\0\0\34\1\0\0\0\0\0\0", 832) = 832
    30072 fstat(4, {st_dev=makedev(0x8, 0x1), st_ino=4316040, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=1400, st_size=711888, st_atime=1592127252 /* 2020-06-14T21:34:12.009638613+1200 */, st_atime_nsec=9638613, st_mtime=1592123947 /* 2020-06-14T20:39:07+1200 */, st_mtime_nsec=0, st
    _ctime=1592127203 /* 2020-06-14T21:33:23.342523653+1200 */, st_ctime_nsec=342523653}) = 0
    30072 mmap(NULL, 2825360, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x7fa4de808000
    30072 mprotect(0x7fa4de8b1000, 2093056, PROT_NONE) = 0
    30072 mmap(0x7fa4deab0000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0xa8000) = 0x7fa4deab0000
    30072 mmap(0x7fa4deab6000, 15504, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fa4deab6000
    30072 close(4)                          = 0
    30072 mprotect(0x7fa4deab0000, 8192, PROT_READ) = 0
    30072 prctl(PR_SET_DUMPABLE, SUID_DUMP_DISABLE) = 0
    30072 openat(AT_FDCWD, "/proc/self/status", O_RDONLY) = 4
    30072 fstat(4, {st_dev=makedev(0, 0x4), st_ino=54465736, st_mode=S_IFREG|0444, st_nlink=1, st_uid=0, st_gid=0, st_blksize=1024, st_blocks=0, st_size=0, st_atime=1592127306 /* 2020-06-14T21:35:06.536646597+1200 */, st_atime_nsec=536646597, st_mtime=1592127306 /* 2020-06-14T21:35:06.536646597+1200 */, st_mtime_nsec=53
    6646597, st_ctime=1592127306 /* 2020-06-14T21:35:06.536646597+1200 */, st_ctime_nsec=536646597}) = 0
    30072 read(4, "Name:\tpython3.7\nUmask:\t0022\nState:\tR (running)\nTgid:\t30072\nNgid:\t0\nPid:\t30072\nPPid:\t30069\nTracerPid:\t30069\nUid:\t0\t0\t0\t0\nGid:\t0\t0\t0\t0\nFDSize:\t64\nGroups:\t0 29 115 \nNStgid:\t30072\nNSpid:\t30072\nNSpgid:\t30069\nNSsid:\t24028\nVmPeak:\t  105600 kB\nVmSize:\t  105600 kB\nVmLc
    k:\t       0 kB\nVmPin:\t       0 kB\nVmHWM:\t   54080 kB\nVmRSS:\t   54080 kB\nRssAnon:\t   35980 kB\nRssFile:\t   18100 kB\nRssShmem:\t       0 kB\nVmData:\t   36708 kB\nVmStk:\t     132 kB\nVmExe:\t    2388 kB\nVmLib:\t   19004 kB\nVmPTE:\t     232 kB\nVmSwap:\t       0 kB\nHugetlbPages:\t       0 kB\nCoreDumpin
    
  • ERROR    The option

    ERROR The option "-n" could not be used as the extra options

    I ran the following command and got an error.

    pyarmor pack -e " --onedir --noconsole --icon icon.ico -n MyAppName" main.py The error message is this,

    ERROR The option "-n" could not be used as the extra options It worked in previous versions but not in version 7.5.1.

    I do not understand which version of PyArmor it worked on as my previous PC is broken. How can I specify my app name?

  • encrypt string values in python

    encrypt string values in python

    Is your feature request related to a problem? Please describe. When decompyling with uncompyle or similar tools on string values and API strings can be seen in pyarmor

    Describe the solution you'd like must be a way to encrypt anything between ' " ' and ' " ' and then decrypt during run time

  • Publishing and installing obfuscated package from pip

    Publishing and installing obfuscated package from pip

    Hey, I am trying to publish an obfuscated package to pip and then install it. I am following this doc: https://pyarmor.readthedocs.io/en/latest/advanced.html#distributing-obfuscated-package-with-pip

    I have kept a similar project structure to the one mentioned in the docs above, but on the step: pyarmor runtime -O dist/share --enable-suffix 1 it does not generate a unique named folder (like pytransform_vax_xxxxxx). It generated a structure as follows:

    .
    |____ share
    | |____ pytransform
    | | |____ __init__.py
    | | |____ _pytransform.dylib
    | |____ pytransform_bootstrap.py
    | |____ pytransform_protection.py
    

    included it in setup.py as:

    data_files=[('pytransform', ['dist/share/pytransform/__init__.py',
                     'dist/share/pytransform/_pytransform.dylib',
                                             'dist/share/pytransform_bootstrap.py',
                                             'dist/share/pytransform_protection.py'])]
    

    And then ran pythom -m build using the above setup.py.

    The above files which are required to de-obfuscate are not available to the pip package on download. I found this in the docs: https://pyarmor.readthedocs.io/en/latest/questions.html#python-import-system, since I had included the files in data_files field it should be available after installing from pip.. could you help with understanding what I am missing here. Thanks!

  • Obfuscated codebase running 10x slower

    Obfuscated codebase running 10x slower

    I have obfuscated my python code base with a purchased licence. I obfuscated my code using the below modes:

    MODE = 0 obf-mode = 0 wrap-mode = 0

    The performance after obfuscation has reduced by 10x. The same code that used to take around 8 seconds is taking ~85 seconds. The code is running inside an UWSGI app and the platform is linux. Could you please provide a resolution for this?

  • Can not import AES from Crypto.Cipher

    Can not import AES from Crypto.Cipher

    On MacOS 12.3.1 run pyarmor to obfuscate the script inside the docker container, python 3.7, PyArmor 7.5.1

    $ PYTHONOPTIMIZE=2 pyarmor obfuscate --advanced 5 --exclude core/internal/code/api/streamer.py --src="." -r --output=/new_app entry.py 
    

    makes success obfuscation, but after running project I got such exception:

    File "<frozen core.internal.code.services.encryption>", line 6, in spp_caller
    AttributeError: module 'Crypto.Cipher' has no attribute 'AES'
    

    Tried use pycrypto, pycryptodome and pycryptodomex. The same error.

AML Command Transfer. A lightweight tool to transfer any command line to Azure Machine Learning Services

AML Command Transfer (ACT) ACT is a lightweight tool to transfer any command from the local machine to AML or ITP, both of which are Azure Machine Lea

Jun 7, 2022
A cd command that learns - easily navigate directories from the command line

NAME autojump - a faster way to navigate your filesystem DESCRIPTION autojump is a faster way to navigate your filesystem. It works by maintaining a d

Jul 5, 2022
Ros command - Unifying the ROS command line tools
Ros command - Unifying the ROS command line tools

Unifying the ROS command line tools One impairment to ROS 2 adoption is that all

Jun 5, 2022
A very simple and lightweight ToDo app using python that can be used from the command line
A very simple and lightweight ToDo app using python that can be  used from the command line

A very simple and lightweight ToDo app using python that can be used from the command line

Nov 29, 2021
Python command line tool and python engine to label table fields and fields in data files.

Python command line tool and python engine to label table fields and fields in data files. It could help to find meaningful data in your tables and data files or to find Personal identifable information (PII).

Jul 3, 2022
PwnWiki command line searching tool & bindings written in Python
PwnWiki command line searching tool & bindings written in Python

pwsearch PwnWiki 数据库搜索命令行工具。 安装 您可以直接用 pip 命令从 PyPI 安装 pwsearch: pip3 install -U pwsearch 您也可以 clone 该仓库并直接从源码启动

Jun 21, 2021
A command line tool (and Python library) for archiving Twitter JSON

A command line tool (and Python library) for archiving Twitter JSON

Jul 2, 2022
Unofficial Open Corporates CLI: OpenCorporates is a website that shares data on corporations under the copyleft Open Database License. This is an unofficial open corporates python command line tool.
Unofficial Open Corporates CLI: OpenCorporates is a website that shares data on corporations under the copyleft Open Database License. This is an unofficial open corporates python command line tool.

Unofficial Open Corporates CLI OpenCorporates is a website that shares data on corporations under the copyleft Open Database License. This is an unoff

Jun 27, 2022
Professor Wordlist is a free open source command line tool written in python

Professor Wordlist is a free open source command line tool written in python, With the aim of generating custom wordlists with a variety of unique parameters and functions providing many possibilities.

Oct 28, 2021
A simple command line tool written in python to manage a to-do list

A simple command line tool written in python to manage a to-do list Dependencies: python Commands: todolist (-a | --add) [(-p | --priority)] [(-l | --

Nov 2, 2021
A command line tool made in Python for the popular rhythm game
A command line tool made in Python for the popular rhythm game

osr!name A command line tool made in Python for the popular rhythm game "osu!" that changes the player name of a .osr file (replay file). Example: Not

Dec 28, 2021
A command line tool to query source code from your current Python env
A command line tool to query source code from your current Python env

wxc wxc (pronounced "which") allows you to inspect source code in your Python environment from the command line. It is based on the inspect module fro

Apr 24, 2022
spotifytools is a Python command line tool

spotifytools spotifytools is a Python command line tool Documentation The documentation is available on the following link Releases Instalation instru

Sep 28, 2021
MsfMania is a command line tool developed in Python that is designed to bypass antivirus software on Windows and Linux/Mac in the future
MsfMania is a command line tool developed in Python that is designed to bypass antivirus software on Windows and Linux/Mac in the future

MsfMania MsfMania is a command line tool developed in Python that is designed to bypass antivirus software on Windows and Linux/Mac in the future. Sum

Jun 27, 2022
Bonjour Software pypahe is a Python Package Helper command-line tool.

pypahe Bonjour Software pypahe is a Python Package Helper command-line tool. Requirements Docker runtime Usage print the latest available version of a

Aug 10, 2021
Python library and command line tool for interacting with Bugzilla

python-bugzilla This package provides two bits: bugzilla python module for talking to a Bugzilla instance over XMLRPC or REST /usr/bin/bugzilla comman

Jun 2, 2022
💻VIEN is a command-line tool for managing Python Virtual Environments.

vien VIEN is a command-line tool for managing Python Virtual Environments. It provides one-line shortcuts for: creating and deleting environments runn

Mar 19, 2022
A python based command line tool to compare Github Users or Repositories

gitcomp A simple python package with a CLI to compare GitHub users and repositories by associating a git_score to each entry which is a weighted sum o

Mar 26, 2022