目錄

廣告 AD

Pyarmor:混淆 Python 腳本,保護你的程式

廣告 AD

Github - Pyarmor
Homepage - Pyarmor

Pyarmor 是一個由 Dashingsoft 公司 (德新软件科技有限公司) 推出用來混淆 Python Script 的一個工具,透過混淆,可以防止有心人士查看裡面的程式碼,保護你的程式。有分為免費版本和付費版本,對付費版本有興趣的可以自己去看官方的頁面。

甚至還有 web 介面供用戶使用

Github - Pyarmor-WebUI

安裝方式很簡單,直接用 pip 安裝即可:

pip install -U pyarmor

如果只有一個單獨的 Python Script 需要加密,則直接使用以下指令就可以了

pyarmor gen <path/to/script>

# Example
pyarmor gen test.py

我們用簡單的 Hello World 腳本來測試一下:

def hello_world():
    print("Hello World")

if __name__ == "__main__":
    hello_world()

跑完指令後,接著你會看到產生出一個 dist 的資料夾,裡面有這個這樣的結構:

.
└── dist/
    ├── test.py
    └── pyarmor_runtime_000000/
        ├── __init__.py
        └── pyarmor_runtime.pyd

我們直接執行 dist 資料夾內的 test.py,你會發現跟直接執行 test.py 是一樣的

如果你要直接 Release 給別人的話,可以直接將 dist 連同裡面所有檔案傳給別人就好了,對方不需要安裝 Pyarmor,只要用安裝相同版本的 Python 執行即可,作業系統也是需要是一樣的


>>> import test 
>>> dir(test)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__pyarmor__', '__spec__', 'hello_world']

有時候為了防止其他人透過 dir 偷看裡面的資訊,我們可以加上 --private 來防止透露一些 function 和 attribute 的資訊

pyarmor gen --private <path/to/script>

# Example
pyarmor gen --private test.py

這時候我們跑看看 dir,就會出現 RuntimeError

>>> import test
>>> dir(test)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: unauthorized use of script (1:5174)

>>> import test
>>> test.hello_world()
Hello World
>>> test.hello_world = lambda: print("Hacked")
>>> test.hello_world()
Hacked

透過上面的方法,我們可以偷換裡面的 function,甚至繞過某些檢查機制,但我們可以加上 --assert-call 來防止這件事情

pyarmor gen --assert-call <path/to/script>

# Example
pyarmor gen --assert-call test.py

接著再試一次,就出現 RuntimeError 了

>>> import test
>>> test.hello_world()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: unauthorized use of script (1:5174)
>>> dir(test)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: unauthorized use of script (1:5174)

如果是 package 需要加密,也是直接使用以下指令就可以了

pyarmor gen <path/to/package>

# Example
pyarmor gen test

執行完後,你會看到產生出一個 dist 的資料夾,裡面有這個這樣的結構:

.
└── dist/
    ├── test/
    │   ├── __init__.py
    │   └── func.py
    └── pyarmor_runtime_000000/
        ├── __init__.py
        └── pyarmor_runtime.pyd

如果你要直接 Release 給別人的話,可以直接將 dist 連同裡面所有檔案傳給別人就好了,對方不需要安裝 Pyarmor,只要用安裝相同版本的 Python 執行即可,作業系統也是需要是一樣的,但你會發現 testpyarmor_runtime_000000 是分開的,這樣其實不太方便,也很容易放錯位置,所以可以在 obfuscating 的時候加上 -i,這樣 pyarmor_runtime_000000 就會被放到 test 裡面,這樣只要給別人 test 資料夾就可以了~

.
└── dist/
    └── test/
        ├── __init__.py
        ├── func.py
        └── pyarmor_runtime_000000/
            ├── __init__.py
            └── pyarmor_runtime.pyd

假設資料夾結構如下:

.
└── test/
    ├── __init__.py
    ├── func.py
    └── utils.py

然後 __init__.py 的檔案裡面有 import func,但沒有 import utils

from .func import hello_world

我們直接執行,還是能透過 test 匯入 utils 並執行裡面的 function

>>> import test
>>> test.hello_world()
hello_world
>>> from test import utils
>>> utils.hello_world()
hello_world

我們可以透過 --restrict 避免這種狀況

pyarmor gen -i --restrict <path/to/package>

# Example
pyarmor gen -i --restrict test

這樣只有 __init__.py 不受限制,其餘 modules 對外面來說都是不可見的

>>> import test
>>> test.hello_world()
hello_world
>>> from test import utils
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<frozen test.utils>", line 3, in <module>
RuntimeError: unauthorized use of script (1:1125)

Pyarmor 有提供設定有效期限的功能,可以設定有效天數或是指定的日期

pyarmor gen -e <days>/<date> <path/to/script>

# Example
pyarmor gen -e 2025-10-26 test.py 
pyarmor gen -e 15 test.py 

如果過期的話,會顯示以下的錯誤:

>>> import test
RuntimeError: this license key is expired (1:11086)
警告
這個日期預設是讀取本地時間,所以可以透過修改本地時間繞過,如果想要採用時間伺服器作為判定方法的話,可以參考官方文件 Link

Pyarmor 也還可以綁定裝置,透過讀取裝置的硬體資訊,可以綁定腳本到特定的機器上,防止使用者使用不合法的機器運行。我們可以透過下面的指令顯示當前機器的資訊,用於後續綁定

python -m pyarmor.cli.hdinfo
Machine ID: 'xxxxxxxxxxxxxx'
Default Harddisk Serial Number: 'xxxxxxxxxxxxxx'
Multiple Mac addresses: xxxxxxxxxxxxxx
Domain: 'xxxxxxxxxxxxxx'

我們可以透過以下指令綁定:

pyarmor gen -b <binding info> <path/to/script>

# Example
pyarmor gen -b 00:00:00:00:00:00 test.py 

如果不是綁定的裝置的話,會顯示以下的錯誤:

>>> import test
RuntimeError: this license key is not for this machine (1:10166)

>>> import test
>>> test.print_value()
Value = 10
>>> test.value = 1
>>> test.print_value()
Value = 1

1

如果要防止有心人士偷改 attribute,最簡單的方式就是設定成 READ-ONLY 的模式,可以透過以下指令:

pyarmor cfg readonly_module=1

重新混淆一次後,現在會出現 RunteimError 了

>>> import test
>>> test.print_value()
Value = 10
>>> test.value = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: protection exception (16782406)

我們一樣可以打包混淆過的 Python Script,記得先安裝 PyInstaller

pip install pyinstaller

打包成 Single File

pyarmor gen --pack onefile <path/to/script>

# Example
pyarmor gen --pack onefile test.py

打包成一個 Folder

pyarmor gen --pack onedir <path/to/script>

# Example
pyarmor gen --pack onedir test.py


廣告 AD