Python 代码混淆和加密技术
1. 背景
Python进行商业开发时, 需要有一定的安全意识, 为了不被轻易的逆向还原. 混淆和加密就有所必要了.
2. 目前的混淆和加密方案
2.1 混淆
- 减少py文件的注释、对代码顺序进行重排:混淆力度不够
- 设计规则编写脚本或者使用现成的混淆工具,将对应的变量、函数、文件名、类名等进行不同程度的无意义的字符串替换:
单个文件或许可行,整个项目处理起来问题较多,涉及模块引用,配置引用的问题(配置无法同步混淆,到时读取出错)
2.2 加密
- 只发行 pyc: 可以用现成工具复原
- 用打包 exe 打包: 可以用现成工具复原
- cython: 要加密单一的模块 /特制算法很有效,不过对很多模块的源代码容易出问题
- 改字节码的 python: 未丢失信息,容易复原
3. 现有混淆和加密工具介绍
3.1 混淆工具
pyminifier
pyminifier是一个对Python文件进行压缩、混淆的工具,项目地址 https://github.com/liftoff/pyminifier
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZlbJBjnL-1626917811900)(./images/mix/pyminifier.png)]
pip 安装
pip install pyminifier
运行命令,把混淆后的输出重定向文件即可
pyminifier ./helloWorld.py > new.py
默认命令只是对代码顺序进行重排和减少注释,如果需要混淆代码需要加上参数
# O 为大写
pyminifier -O ./helloWorld.py > new.py
注: 目前pyminifier只能处理单个文件,而且部分脚本混淆后不可运行,需要手动测试
Oxyry Python Obfuscator
Oxyry Python Obfuscator是一个在线混淆代码的工具,地址是 http://pyob.oxyry.com/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sjghm1VZ-1626917811902)(./images/mix/oxyry.png)]
注:目前Oxyry也只能混淆单个Python文件,测试过混淆后代码可用
Opy
Opy也是一个代码混淆工具,可以对整个目录的Python文件进行混淆处理,并且支持定义混淆格式,项目地址 https://github.com/QQuick/Opy
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mm3OjM38-1626917811907)(./images/mix/opy.png)]
注:经过测试,混淆后的Python项目不可直接执行,不建议使用
ZFJPyMix
ZFJPyMix具有混淆文件名、混淆类名、混淆属性变量名、混淆方法名和删除注释来混淆Python源码,具体功能结构图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ML6yEUxz-1626917811918)(./images/mix/ZFJPyMix.jpg)]
具体可以看博客 : https://zfj1128.blog.csdn.net/article/details/102825025
总结:混淆的方式,只要是开源的代码,就有被逆转的可能,且整个项目混淆后,可以运行起来的可能性微乎其微
3.2 加密工具
compile、compileall
compile、compileall 是python 自带的工具,可以将py 文件编译成 pyc 、pyo 文件,
py是源文件,pyc是源文件编译后的文件,pyo是源文件优化编译后的文件。
# compile
import py_compile
py_compile.compile(r'H:/game/test.py')
# compileall 批量编译
import compileall
compileall.compile_dir(r'H:/game')
cython 官方文档
Cython是属于Python的超集,Cython可以将 Python文件转换成c, 并编译成pyd文件(Linux 或 Mac 下为 so 文件)。一般将核心模块编译成pyd, 这样被破解的风险就大大降低了.
- 优势:资源丰富,适合快速开发。翻译成C后速度比较快。
- 缺点:但需要编写额外的代码来生成C模块,并且生成后的模块不一定可以直接运行。
安装
pip install Cython
准备要加密的 py 文件 (test.py)
def hello_world():
print("hello world!!!")
编写 setup.py 脚本
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize(["test.py"]))
执行完就会得到一份 pyd / so 文件, 然后创建另一份文件 (test_helloWorld.py)
# 引入
from test import hello_world
# 调用
hello_world()
命令行执行 test_helloWorld.py
python test_helloWorld.py
# 输出
hello world!!!
总结:加密的方式,对比混淆的方式,被破解的风险大大降低,但需要自行编写脚本,成本高,加密后的项目还不一定能够成功运行
Wefe 项目python 模块的代码加密就是基于 cython进行的,由于cython 本身的一些限制,结合项目,在加密过程中也遇到过一些问题,部分跟序列化相关的文件
无法进行加密,最后采用 cython + compile 的方式,把无法转为 pyd 的py文件,转成pyc ,也能一定程度上保护项目的代码