天天看點

想了解Python源代碼加密嗎?現總結如下5大加密混淆手段!

作者:梓羽Python

我們在進行Python技術開發時,特别是腳本、元件、工具類開發的時候,在提測或上線的時候需要把實際的工具腳本交由實際執行者,以免一些代碼内的敏感資訊洩漏或者可以随意更改元件工具導緻一些不可控制的問題。我們常常還是會采取一系列手段,對Python代碼進行加密、編譯、混淆以保護我們的工程。

現介紹以下幾種源碼保護手段:

1.編譯.pyc檔案

pyc檔案是一種二進制檔案,由原生Python檔案經過編譯後所生成的,py檔案編譯成pyc檔案後加載速度更快而且提高了代碼的安全性。pyc的内容與python的版本相關,不同版本編譯的pyc檔案不一樣

單個pyc檔案的生成

一般正常情況下,我們運作py腳本,其包括所依賴的腳本都會在所在目錄下自動編譯生成.pyc檔案。這次我們主要看下如何通過指令方式主動生成.pyc檔案

python -m py_compile py檔案絕對路徑

pyc會生成在目錄下的__pycache__下(前後有雙下劃線)
生成的檔案名命名方式:源檔案名.cpython-python版本.pyc           
想了解Python源代碼加密嗎?現總結如下5大加密混淆手段!

批量pyc檔案的生成

通過compile_dir方法指定目錄,會将其目錄下所有py檔案全部編譯為pyc檔案

compile_dir(dir[, maxlevels[, ddir[, force[, rx[, quiet]]]]])
參數含義:
– maxlevels:遞歸編譯的層數
– ddir:If ddir is given, it is prepended to the path to each file being compiled for use in compilation time tracebacks, and is also compiled in to the byte-code file, where it will be used in tracebacks and other messages in cases where the source file does not exist at the time the byte-code file is executed.
– force:如果True,不論是是否有pyc,都重新編譯
– rx:一個正規表達式,排除掉不想要的目錄
– quiet:如果為True,則編譯不會在标準輸出中列印資訊
python -m compileall <dir>           

2.打包為exe

打包Python程式的三方開源庫很多,這裡主要推薦兩種常用且效果不錯的打包庫:PyInstaller、Nuitka

名稱 License Qt6 Qt5 Linux Windows macOS
PyInstaller GPL 部分支援 支援 支援 支援 支援
Nuitka MIT 支援 支援 支援 支援 支援

PyInstaller

PyInstaller是一個第三方庫,它能夠在Windows、Linux、 Mac OS X 等作業系統下将 Python源檔案進行打包,打包完成後,exe即可在沒有Python 的環境中運作,也可以作為一個獨立檔案友善傳遞和管理。

PyInstaller可以在Windows、Mac OS X和Linux上使用,但是并不是跨平台的,是以打包成.exe檔案,需要在Windows系統上運作PyInstaller進行打包工作;打包成mac app,需要在Mac OS上使用。

安裝:

pip install pyinstaller           

pyinstaller将單個py檔案打包

使用:

Pyinstaller -F demo.py -- 打包exe
Pyinstaller -F -w demo.py -- 不帶控制台的打包 不帶黑框 
Pyinstaller -F -i test.ico demo.py -- 打包指定exe圖示打包
常用選項:
-h,–help 檢視該子產品的幫助資訊
-F,-onefile 産生單個的可執行檔案
-D,–onedir 産生一個目錄(包含多個檔案)作為可執行程式
-a,–ascii 不包含 Unicode 字元集支援
-d,–debug 産生 debug 版本的可執行檔案
-w,–windowed,–noconsolc 指定程式運作時不顯示指令行視窗(僅對 Windows 有效)
-c,–nowindowed,–console 指定使用指令行視窗運作程式(僅對 Windows 有效)
-o DIR,–out=DIR 指定 spec 檔案的生成目錄。如果沒有指定,則預設使用目前目錄來生成 spec 檔案
-p DIR,–path=DIR 設定 Python 導入子產品的路徑(和設定 PYTHONPATH 環境變量的作用相似)。也可使用路徑分隔符(Windows 使用分号,Linux 使用:号)來分隔多個路徑
-n NAME,–name=NAME 指定項目(産生的 spec)名字。如果省略該選項,那麼第一個腳本的主檔案名将作為 spec 的名字
-i 選擇圖示           
想了解Python源代碼加密嗎?現總結如下5大加密混淆手段!

pyinstaller将多個py檔案打包

生成spec規範配置檔案:

pyi-makespec demo.py

pyinstaller [-F/-D] [-w/-c] [-i xxx.ico] demo.py

# -*- mode: python ; coding: utf-8 -*-
block_cipher = None #設定 加密,需要安裝tinyaes第三方庫,最多16位字元,此處在使用--key= 會有變化
a = Analysis(
['demo.py'], # 運作的所有py檔案,包括依賴的py檔案
pathex=[], # 搜尋導入的路徑清單(此清單為項目絕對路徑),包括選項給出的路徑--paths,項目需要從什麼地方導入自定義庫
binaries=[], # 腳本需要的非python子產品,包括--add-binary選項給出的名稱,二進制資料
datas=[], # 應用程式中包含的非二進制檔案,包括--add-data選項給出的名稱,項目需要用到什麼資料,比如圖檔,視訊等。裡面格式為tuple,第一個參數是檔案路徑,第二個是打包後所在的路徑,其為一個元組:('image/*.png','data/image')
hiddenimports=[], # 假如打包後打開exe顯示module not found,就要把該庫添加到hiddenimports裡面了
hookspath=[],
hooksconfig={}, # 挂鈎配置選項由一個字典組成
runtime_hooks=[],
excludes=[], # 假如你用的python有很多庫,但是你不需要用到某個,那麼就把它添加到裡面去,可以壓縮檔案大小
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts, # 打包的腳本檔案
# a.binaries, # 如果是單檔案模式,則需要添加;多檔案也可以添加
# a.zipfiles,
# a.datas,
[],
exclude_binaries=True, # 是否排除二進制檔案,為True時,為排除二進制的檔案,當檔案交大時包含二進制檔案運作較快,如果是單檔案,則沒有這個選項
name='demo', # 打包程式的名字
debug=False, # 是否啟用調試功能
bootloader_ignore_signals=False,
# runtime_tmpdir=None, # 生成單檔案時需要這個參數,定義運作時的臨時檔案夾
strip=False,
upx=True, # 打包的時候進行壓縮,False表示不壓縮;要用到一個壓縮程式UPX,用于壓縮檔案,需要單獨下載下傳
console=True, # 打包後的可執行檔案輕按兩下運作時螢幕會出現一個cmd視窗,不影響原程式運作,等于是是否加-w參數
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,

"""添加選項,初始化時沒有的"""
icon="", # 指定應用程式的圖示,傳入路徑,可以相對路徑

)
coll = COLLECT(
"""
如果是單檔案模式,不需要這個COLLECT類,同時需要将:
a.binaries,
a.zipfiles,
a.datas,
這些資料檔案添加到EXE中
"""
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='main',
)           

項目打包:

pyinstaller demo.spec           

這樣即可将python程式打包成一個獨立的應用工具,直接運作即可。實作了保護程式的一個作用(當然也是可以反編譯成功的,不過也提升了破解的難度)

Nuitka

nuitka則是将python源碼轉成C++(這裡得到的是二進制的pyd檔案,防止了反編譯),然後再編譯成可執行檔案。

安裝:

pip install -U nuitka           

安裝MinGW64:

Windows環境需安裝MinGW64,搭建gcc編譯環境

MacOS環境不需要單獨下載下傳,它會在安裝nuitka時自動下載下傳gcc

下載下傳位址:https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/

打包:

nuitka --mingw64 xxx.py # 單純打包
nuitka --mingw64 --standalone --show-progress --show-memory --enable-plugin=pyqt5 --output-dir=out demo.py # 指定參數打包
選項說明:
--mingw64:環境選擇
--standalone:是否獨立環境
--show-progress:展示過程
--show-memory:顯示記憶體
--plugin-enable=qt-plugins:qt配置
--include-qt-plugins=sensible,styles:qt樣式保持
--recurse-all:導入引入的資源           

nuitka打包并不像網上說的那樣,打包速度快,打包體積小。我也實測過,目前體檢的感覺就是資源方面的确不用我們考慮那麼深,不像pyinstaller可能相關配置就弄好了,打包還是會報資源缺失。而且打包的速度比較慢,體積也挺大的,但是畢竟也是可達到保護Python程式的目的,給使用者友善。

3.代碼Obfuscator混淆

借助oxyry線上網站實作obfuscator混淆

線上位址:https://pyob.oxyry.com/

想了解Python源代碼加密嗎?現總結如下5大加密混淆手段!

使用 pyobfuscate 庫進行混淆

pyobfuscate 會對代碼中使用者定義的類、函數、變量等進行重命名、更改代碼縮進(預設1)、移除注釋、添加不影響邏輯的代碼語句,最終起到混淆的作用。不過 pyobfuscate 使用 Python2 編寫,無法解析 Python3 中的 f-string 等特殊文法,是以使用前需要将源碼進行一定程度的修改,當然也可以直接修改 pyobfuscate 庫,增加對 Python3 版本的支援。

python pyobfuscate.py demo.py > demo_obfuscated.py           

兩種主要都是對類和函數名等進行了重置替換,增加閱讀難度

4.使用 Cython

使用Cython進行開發

編寫檔案hello.pyx或hello.py:

def hello():
    print('hello')           

編寫setup.py:

from distutils.core import setup
from Cython.Build import cythonize

setup(name='Hello World app',
     ext_modules=cythonize('hello.pyx'))           

編譯為.c,再進一步編譯為.so或.pyd:

python setup.py build_ext --inplace
python -c "from hello import hello;hello()" # 即可直接引用生成的二進制檔案中的hello()函數。           

生成的二進制 .so 或 .pyd 檔案難以破解同時帶來了性能提升

5.PyArmor

PyArmor 是一個用于加密和保護 Python 腳本的工具。它能夠在運作時刻保護 Python腳本的二進制代碼不被洩露,設定加密後 Python 源代碼的有效期限,綁定加密後的Python源代碼到硬碟、網卡等硬體裝置。它的保障機制主要包括:

  • 加密編譯後的代碼塊,保護子產品中的字元串和常量
  • 在腳本運作時候動态加密和解密每一個函數(代碼塊)的二進制代碼
  • 代碼塊執行完成之後清空堆棧局部變量
  • 通過授權檔案限制加密後腳本的有效期和裝置環境

除了對 Python 代碼進行加密,PyArmor 還能設定 Python 程式的許可方式,比如設定程式的使用期限、設定允許運作的裝置、擴充其他認證方式等

安裝:

pip install pyarmor           

使用 obfuscate 選項對代碼進行加密:

pyarmor obfuscate demo.py           

使用 licenses 選項生成許可檔案:

pyarmor licenses \ 
--expired "2023-03-11" \ 
--bind-disk "10030SFTUF3NJ5T" \ 
--bind-mac "56:f1:a7:64:f0:64" \ 
--bind-ipv4 "211.110.6.54" \ 
r001           

使用 pack 選項即可打包腳本:

pyarmor pack demo.py           

不過這款工具屬于試用階段,傾向于商業模式,可以學習試試。

以上5種方式都可提升程式的安全性,保護項目敏感資訊。如果對外釋出的,也可提升破解難度。今天的分享就到這裡了,歡迎留言讨論。