前言
- 防止
Python
可执行文件(.exe)被反编译是一项重要的安全措施,尤其是当你希望保护你的知识产权、算法、或者商业逻辑时。虽然绝对的安全是不存在的,但可以采取一些措施来增加反编译的难度,使得攻击者更难以获取你的源代码。
常用方案
pyinstaller
使用 --key
进行加密
- 我们可以在打包命令后面添加
--key
参数来进行加密,例如:
pyinstaller --onefile -p venv/Lib/site-packages .print-studentmain.py --key '1234'
- 再次解压,抽取的中间结果变为了
.pyc.encrypted
,无法正常反编译。
PyInstaller v6.0
移除加密命令
Bytecode encryption was removed in PyInstaller v6.0. Please remove your --key=xxx argument. For the rationale and alternatives see https://github.com/pyinstaller/pyinstaller/pull/6999
- 官方
github
的一些讨论:
- 大概的意思就是说,解密密钥必须存储在构建的应用程序中的某个位置以使应用程序能够运行,字节码加密对于窥探的眼睛只能起到轻微的威慑作用。任何愿意挖掘
PyInstaller
源代码以获取可执行存档的确切布局和快速十六进制转储的人都可以破解它,一旦您知道在哪里查找即可获取密钥。 - 然而现在,像
PyExtractor
这样的PyInstaller
逆向工程工具已经内置了这一切。例如,在下面的步骤中,我们的窥探用户甚至不需要知道他们试图打开的应用程序是加密的,更不用说必须采取任何巧妙的措施来解密它。
git clone https://github.com/Rdimo/PyExtractor.git
cd PyExtractor
pip install -r requirements.txt
python main.py some/pyinstaller/application
- 由于逆向工程的知识障碍,加密构建现在与常规构建相同,用户可能被误导认为加密的
PyInstaller
构建是放置 API 密钥等内容的安全位置。最后即使添加了更多代码混淆最终会导致相同的结果,因此完全删除加密功能。 - 当然也有朋友提出将加密密码交给使用者运行时填入,但是对于源码的加密实际上并没有很大的实际意义,且会增加维护成本。
使用Cython配合加密打包程序
Python
在打包或优化运行速度时会生成.pyc文件,类似于Java
的.class文件。这些.pyc文件可以被简单地反编译为.py文件,就像Java
的.class文件可以反编译为Java
源代码一样。然而,相比之下,由C语言编译生成的机器码更难以反编译。实际上,机器码反编译后通常是汇编代码或难以阅读的C语言代码。目前还没有一种直接将机器码转换回Python
代码的方法。因此,我们可以利用这一点来加密我们的代码。Cython
是一个编译器,可以将Cython
源代码转换为高效的C或C
源代码。然后,我们可以将这些源代码编译 为Python
扩展模块或独立的可执行文件。通过使用Cython
将我们的Python
代码转换为C或C ,可以大大增加反编译的难度。
安装 Cython
代码语言:txt复制pip install cython
配置 Cython
文件 & 编译
- 配置
build_pyd.py
文件:
from distutils.core import setup
from Cython.Build import cythonize
setup(
name='一个名字',
ext_modules=cythonize(
[
"Python脚本文件.py",
"Python脚本文件夹/*.py",
# ...
],
language_level=3
),
)
// 编译
python build_pyd.py build_ext --inplace
- 可以看到生成了一些.pyd文件,这是Windows的DLL文件,相对来说破解和反编译都比.pyc文件要难一些,可以达到一定的加密效果。生成.pyd文件后的目录结构:
│ app.c
│ app.cp38-win_amd64.pyd
│ app.py
│ build_pyd.py
│ config.c
│ config.cp38-win_amd64.pyd
│ config.py
│ gui.c
│ gui.cp38-win_amd64.pyd
│ gui.py
│ log.c
│ log.cp38-win_amd64.pyd
│ log.py
│ run.py
│
├─.idea
│ ......省略......
│
├─build
│ ......省略......
│
├─images
│ icon.ico
│
├─logs
│ ......省略......
│
├─venv
│ ......省略......
│
└─__pycache__
重新打包
代码语言:txt复制pyinstaller -F run.py --hidden-import json --hidden-import tkinter --hidden-import tkinter.filedialog --hidden-import requests --hidden-import docx --hidden-import openpyxl --hidden-import log --hidden-import gui --hidden-import tkinter.ttk --hidden-import config
- 当我们将
Python
源文件编译成.pyd文件时,由于.pyd文件是二进制文件,PyInstaller
在分析需要导入的包时无法直接解析.pyd文件。导致PyInstaller
不知道.pyd文件中导入了哪些模块。 - 因此,我们需要使用--hidden-import参数告诉
PyInstaller
我们需要导入哪些模块,以便正确地打包应用程序。
总结
- 本文介绍了两种常见的
Python .exe
源码加密方式,但实际上无论哪种方式都无法做到完全加密,只是相对的提高了反编译的难度。简单来说,Python
属于解释型语言,执行器解析的是源码,即使进行加密,运行时也需要解密为源码,不同于C、C
等编译型语言,执行器执行的机器码,机器码的反编译难度指数级上升。
参考
- https://www.cnblogs.com/minuhy/p/17747925.html
个人简介