Python 语言因其简洁明了的语法、易学性、高可读性、广泛的应用领域、强大的库和框架支持以及良好的平台兼容性,赢得了众多开发者的青睐。然而,作为一门脚本语言,Python 脚本由解释器直接从源码(字符流)进行解释执行,这使得其代码安全性成为许多开发者关注的焦点。如果你正在寻找保护 Python 脚本安全的方法,本文为你总结了几种主流的 Python 脚本保护策略,希望能为你的开发工作提供有价值的参考。
由于内容较多,本文将先介绍三种常见的保护方案。
目标读者
- Python 脚本开发者
- 对 Python 代码安全感兴趣的初学者
利用 pyc 文件进行保护
.pyc 文件是 Python 编译脚本后生成的缓存文件,主要用于提升脚本的加载速度。它将代码以一种非源码的形式保存,从而在一定程度上保护了代码的安全性。以下是生成 pyc 文件的代码示例:
python
import marshal
from time import time
import importlib
_bootstrap_external = importlib._bootstrap_external
def _pack_uint32(x):
"""Convert a 32-bit integer to little-endian."""
return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little')
def _code_to_timestamp_pyc(code, mtime=0, source_size=0):
data = bytearray(_bootstrap_external.MAGIC_NUMBER)
data.extend(_pack_uint32(0))
data.extend(_pack_uint32(mtime))
data.extend(_pack_uint32(source_size))
data.extend(marshal.dumps(code))
return data
def codeobject_to_pyc(co, pyc_path):
code_bytes = _code_to_timestamp_pyc(co, int(round(time() * 1000)))
with open(pyc_path, 'wb') as pyc:
pyc.write(code_bytes)
def compile_py(source_path, pyc_path):
with open(source_path, 'rb') as source_file:
source_code = source_file.read()
co = compile(source_code, source_path, 'exec')
codeobject_to_pyc(co, pyc_path)
操作步骤
你可以直接使用上述代码,或者通过命令行执行 python3 -m py_compile test.py
来生成 pyc 文件。
效果展示

存在的不足
- pyc 文件的 Python 版本兼容性较差,不同版本的 Python 可能无法执行同一 pyc 文件。
- 使用 uncompyle 工具可以轻松反编译 pyc 文件,恢复出几乎与原代码一致的 Python 源码。例如,以下是一个反编译后的代码示例:
python
# uncompyle6 version 3.9.2
# Python bytecode version base 3.8.0 (3413)
# Decompiled from: Python 3.8.10 (tags/v3.8.10:3d8993a, May 3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)]
# Embedded file name: .\test.py
# Compiled at: 2016-08-06 10:43:48
import hashlib, uuid
def calculate_serial(str):
hex_representation = str.encode("utf-8").hex()
md5_hash = hashlib.md5(hex_representation.encode("utf-8")).hexdigest()
return md5_hash
def get_verify_serial():
uuid_str = str(uuid.uuid4())
return calculate_serial(uuid_str)
if __name__ == "__main__":
input_str = input("input string:")
serial = calculate_serial(input_str)
verify_serial = get_verify_serial()
if serial == verify_serial:
print("Serial matches the verification serial.")
else:
print("Serial does not match the verification serial.")
脚本级代码混淆
pyminifier 是一款知名的代码混淆工具,它通过随机字符串替换变量名、函数名、类名、导入模块名等标识符,使逆向者难以从名称中获取有用信息。
操作步骤
- 安装 pyminifier:
pip install pyminifier
。 - 执行混淆操作:
pyminifier --obfuscate --nonlatin --replacement-length=32 --gzip --outfile=.\test-pyminifier.py .\test.py
。
效果展示
混淆后的代码示例如下:
python
import zlib, base64
exec(zlib.decompress(base64.b64decode('eJzFV81K41AU3ucpLtmYLMxqBBHyFD5AiM2tudDclORGXCoEZAqjGf8Q0WprTNVS1Gp1hhZ8DxlB0I06kPMI3lRXLlyeLJJAAjnn+zkf5zKv7geCuHbo1tickg9/QrZx/e8Umu0RdBq70BscwunZ8svdPnQ3dyHp/YYkS6HZ2oFu3Mj7MSTtGLaP+pCNtt4GGWSDDqTp8GE17/+Cs/g2v249Z1vQWzl+6izJ367Ja+91RT7Sy/sNMxQBdlVILk5MxuuRQK98uD406wHj6JUf2+fmp8iG50wp7EP3KGIOPgmjvlkUNorbD8WhVYLugO6Bhu51fUZBB5r93TPRgRqUV3yHahORqE5OT+iGSxc1HR98ki5hg5dzhm2sQuOvjI8pd9g8DUVBfEBFFPAy+C9luo9vGloZw9ZsjfCHDd1uMr41vURT4Ud3IayusCqxLG571LJMU7Usz2bcslR8n+UXHWybFSuTpo53JiI3NsbnZ9QyAv0qxkeO7zcpMD65//9coXM7DmqFsBIWQOkkbLiSYRkW6FDlmUNTZ2nA7BrxbFFxaUiES8mCfFVlFVswn5Nw/N0ohprWQlp2n44vm+S++Gj4u3bfAVaa8XY=')))
# Created by pyminifier (https://github.com/liftoff/pyminifier)
存在的不足
混淆后的代码仍然是源码,逆向者可以通过调试或修改混淆后的代码来获取逻辑。例如,通过解码上述代码中的 Base64 数据并解压缩,可以得到混淆后的源码。进一步处理后,代码逻辑仍然可以被理解,如下所示:
python
import hashlib
import uuid
def method1(str):
v1 = str.encode('utf-8').hex()
v2 = hashlib.md5(v1.encode('utf-8')).hexdigest()
return v2
def method2():
v1 = str(uuid.uuid4())
return method1(v1)
if __name__ == "__main__":
v1 = input("input string:")
v2 = method1(v1)
v3 = method2()
if v2 == v3:
print("Serial matches the verification serial.")
else:
print("Serial does not match the verification serial.")
数据文件加密方案
从技术角度看,Python 脚本本质上是一种数据文件,因为 Python 解释器会读取脚本内容并执行。DS Protector 是一款强大的数据文件加密工具,它不仅可以加密 Python 脚本和 pyc 文件,还可以保护 Python.exe,从而增强代码的安全性。
操作步骤
- 将 Python 脚本编译为 pyc 文件。
- 使用 DS Protector 对 pyc 文件进行加密。
- 对 Python.exe 进行保护。
具体操作步骤可以参考官网:lm.virbox.com/docs/site/s...
效果展示

存在的不足
- 加密后的脚本必须由保护后的 Python.exe 执行。
- 如果逆向者具备调试技能,在 Windows 系统上可以通过监控 ReadFile 函数获取解密后的数据,如下图所示:
尽管如此,与前两种保护方式相比,这种方案已经对逆向者的技术水平提出了更高的要求。
本文未完,后续将继续介绍更多 Python 脚本保护方案。