likes
comments
collection
share

加密护盾:保护你的Python .exe程序免受反编译的利器

作者站长头像
站长
· 阅读数 4

前言

  • 防止 Python 可执行文件(.exe)被反编译是一项重要的安全措施,尤其是当你希望保护你的知识产权、算法、或者商业逻辑时。虽然绝对的安全是不存在的,但可以采取一些措施来增加反编译的难度,使得攻击者更难以获取你的源代码。

常用方案

pyinstaller 使用 --key 进行加密

  • 我们可以在打包命令后面添加 --key 参数来进行加密,例如:
 pyinstaller --onefile   -p venv/Lib/site-packages .\print-student\main.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 的一些讨论:

加密护盾:保护你的Python .exe程序免受反编译的利器

加密护盾:保护你的Python .exe程序免受反编译的利器

  • 大概的意思就是说,解密密钥必须存储在构建的应用程序中的某个位置以使应用程序能够运行,字节码加密对于窥探的眼睛只能起到轻微的威慑作用。任何愿意挖掘 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

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__

重新打包

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++ 等编译型语言,执行器执行的机器码,机器码的反编译难度指数级上升。

参考

个人简介

👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.

🚀 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。

🧠 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。

💡 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。

🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

📖 保持关注我的博客,让我们共同追求技术卓越。