Python脚本安全防护策略全解析(上)

Python 语言因其简洁明了的语法、易学性、高可读性、广泛的应用领域、强大的库和框架支持以及良好的平台兼容性,赢得了众多开发者的青睐。然而,作为一门脚本语言,Python 脚本由解释器直接从源码(字符流)进行解释执行,这使得其代码安全性成为许多开发者关注的焦点。如果你正在寻找保护 Python 脚本安全的方法,本文为你总结了几种主流的 Python 脚本保护策略,希望能为你的开发工作提供有价值的参考。

由于内容较多,本文将先介绍三种常见的保护方案。

目标读者

  1. Python 脚本开发者
  2. 对 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 是一款知名的代码混淆工具,它通过随机字符串替换变量名、函数名、类名、导入模块名等标识符,使逆向者难以从名称中获取有用信息。

操作步骤

  1. 安装 pyminifier:pip install pyminifier
  2. 执行混淆操作: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,从而增强代码的安全性。

操作步骤

  1. 将 Python 脚本编译为 pyc 文件。
  2. 使用 DS Protector 对 pyc 文件进行加密。
  3. 对 Python.exe 进行保护。

具体操作步骤可以参考官网:lm.virbox.com/docs/site/s...

效果展示

存在的不足

  1. 加密后的脚本必须由保护后的 Python.exe 执行。
  2. 如果逆向者具备调试技能,在 Windows 系统上可以通过监控 ReadFile 函数获取解密后的数据,如下图所示:

尽管如此,与前两种保护方式相比,这种方案已经对逆向者的技术水平提出了更高的要求。

本文未完,后续将继续介绍更多 Python 脚本保护方案。


相关推荐
R-G-B1 小时前
OpenCV Python——Numpy基本操作(Numpy 矩阵操作、Numpy 矩阵的检索与赋值、Numpy 操作ROI)
python·opencv·numpy·numpy基本操作·numpy 矩阵操作·numpy 矩阵的检索与赋值·numpy 操作roi
细节处有神明1 小时前
Jupyter 中实现交互式图表:ipywidgets 从入门到部署
ide·python·jupyter
小小码农一只1 小时前
Python 爬虫实战:玩转 Playwright 跨浏览器自动化(Chromium/Firefox/WebKit 全支持)
爬虫·python·自动化
杜子不疼.2 小时前
《Python学习之使用标准库:从入门到实战》
开发语言·python·学习
胡耀超3 小时前
从哲学(业务)视角看待数据挖掘:从认知到实践的螺旋上升
人工智能·python·数据挖掘·大模型·特征工程·crisp-dm螺旋认知·批判性思维
tomelrg3 小时前
多台服务器批量发布arcgisserver服务并缓存切片
服务器·python·arcgis
A尘埃3 小时前
Java+Python混合微服务OCR系统设计
java·python·微服务·混合
哈里谢顿3 小时前
Python 依赖注入详解
python
冬天vs不冷4 小时前
Java基础(九):Object核心类深度剖析
java·开发语言·python