想了解Python源代码加密吗?现总结如下5大加密混淆手段!
off999 2024-09-23 11:33 37 浏览 0 评论
我们在进行Python技术开发时,特别是脚本、组件、工具类开发的时候,在提测或上线的时候需要把实际的工具脚本交由实际执行者,以免一些代码内的敏感信息泄漏或者可以随意更改组件工具导致一些不可控制的问题。我们常常还是会采取一系列手段,对Python代码进行加密、编译、混淆以保护我们的工程。
现介绍以下几种源码保护手段:
1.编译.pyc文件
pyc文件是一种二进制文件,由原生Python文件经过编译后所生成的,py文件编译成pyc文件后加载速度更快而且提高了代码的安全性。pyc的内容与python的版本相关,不同版本编译的pyc文件不一样
单个pyc文件的生成
一般正常情况下,我们运行py脚本,其包括所依赖的脚本都会在所在目录下自动编译生成.pyc文件。这次我们主要看下如何通过命令方式主动生成.pyc文件
python -m py_compile py文件绝对路径
pyc会生成在目录下的__pycache__下(前后有双下划线)
生成的文件名命名方式:源文件名.cpython-python版本.pyc
批量pyc文件的生成
通过compile_dir方法指定目录,会将其目录下所有py文件全部编译为pyc文件
compile_dir(dir[, maxlevels[, ddir[, force[, rx[, quiet]]]]])
参数含义:
– maxlevels:递归编译的层数
– ddir:If ddir is given, it is prepended to the path to each file being compiled for use in compilation time tracebacks, and is also compiled in to the byte-code file, where it will be used in tracebacks and other messages in cases where the source file does not exist at the time the byte-code file is executed.
– force:如果True,不论是是否有pyc,都重新编译
– rx:一个正则表达式,排除掉不想要的目录
– quiet:如果为True,则编译不会在标准输出中打印信息
python -m compileall <dir>
2.打包为exe
打包Python程序的三方开源库很多,这里主要推荐两种常用且效果不错的打包库:PyInstaller、Nuitka
名称 | License | Qt6 | Qt5 | Linux | Windows | macOS |
PyInstaller | GPL | 部分支持 | 支持 | 支持 | 支持 | 支持 |
Nuitka | MIT | 支持 | 支持 | 支持 | 支持 | 支持 |
PyInstaller
PyInstaller是一个第三方库,它能够在Windows、Linux、 Mac OS X 等操作系统下将 Python源文件进行打包,打包完成后,exe即可在没有Python 的环境中运行,也可以作为一个独立文件方便传递和管理。
PyInstaller可以在Windows、Mac OS X和Linux上使用,但是并不是跨平台的,所以打包成.exe文件,需要在Windows系统上运行PyInstaller进行打包工作;打包成mac app,需要在Mac OS上使用。
安装:
pip install pyinstaller
pyinstaller将单个py文件打包
使用:
Pyinstaller -F demo.py -- 打包exe
Pyinstaller -F -w demo.py -- 不带控制台的打包 不带黑框
Pyinstaller -F -i test.ico demo.py -- 打包指定exe图标打包
常用选项:
-h,–help 查看该模块的帮助信息
-F,-onefile 产生单个的可执行文件
-D,–onedir 产生一个目录(包含多个文件)作为可执行程序
-a,–ascii 不包含 Unicode 字符集支持
-d,–debug 产生 debug 版本的可执行文件
-w,–windowed,–noconsolc 指定程序运行时不显示命令行窗口(仅对 Windows 有效)
-c,–nowindowed,–console 指定使用命令行窗口运行程序(仅对 Windows 有效)
-o DIR,–out=DIR 指定 spec 文件的生成目录。如果没有指定,则默认使用当前目录来生成 spec 文件
-p DIR,–path=DIR 设置 Python 导入模块的路径(和设置 PYTHONPATH 环境变量的作用相似)。也可使用路径分隔符(Windows 使用分号,Linux 使用:号)来分隔多个路径
-n NAME,–name=NAME 指定项目(产生的 spec)名字。如果省略该选项,那么第一个脚本的主文件名将作为 spec 的名字
-i 选择图标
pyinstaller将多个py文件打包
生成spec规范配置文件:
pyi-makespec demo.py
或
pyinstaller [-F/-D] [-w/-c] [-i xxx.ico] demo.py
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None #设置 加密,需要安装tinyaes第三方库,最多16位字符,此处在使用--key= 会有变化
a = Analysis(
['demo.py'], # 运行的所有py文件,包括依赖的py文件
pathex=[], # 搜索导入的路径列表(此列表为项目绝对路径),包括选项给出的路径--paths,项目需要从什么地方导入自定义库
binaries=[], # 脚本需要的非python模块,包括--add-binary选项给出的名称,二进制数据
datas=[], # 应用程序中包含的非二进制文件,包括--add-data选项给出的名称,项目需要用到什么数据,比如图片,视频等。里面格式为tuple,第一个参数是文件路径,第二个是打包后所在的路径,其为一个元组:('image/*.png','data/image')
hiddenimports=[], # 假如打包后打开exe显示module not found,就要把该库添加到hiddenimports里面了
hookspath=[],
hooksconfig={}, # 挂钩配置选项由一个字典组成
runtime_hooks=[],
excludes=[], # 假如你用的python有很多库,但是你不需要用到某个,那么就把它添加到里面去,可以压缩文件大小
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts, # 打包的脚本文件
# a.binaries, # 如果是单文件模式,则需要添加;多文件也可以添加
# a.zipfiles,
# a.datas,
[],
exclude_binaries=True, # 是否排除二进制文件,为True时,为排除二进制的文件,当文件交大时包含二进制文件运行较快,如果是单文件,则没有这个选项
name='demo', # 打包程序的名字
debug=False, # 是否启用调试功能
bootloader_ignore_signals=False,
# runtime_tmpdir=None, # 生成单文件时需要这个参数,定义运行时的临时文件夹
strip=False,
upx=True, # 打包的时候进行压缩,False表示不压缩;要用到一个压缩程序UPX,用于压缩文件,需要单独下载
console=True, # 打包后的可执行文件双击运行时屏幕会出现一个cmd窗口,不影响原程序运行,等于是是否加-w参数
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
"""添加选项,初始化时没有的"""
icon="", # 指定应用程序的图标,传入路径,可以相对路径
)
coll = COLLECT(
"""
如果是单文件模式,不需要这个COLLECT类,同时需要将:
a.binaries,
a.zipfiles,
a.datas,
这些数据文件添加到EXE中
"""
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='main',
)
项目打包:
pyinstaller demo.spec
这样即可将python程序打包成一个独立的应用工具,直接运行即可。实现了保护程序的一个作用(当然也是可以反编译成功的,不过也提升了破解的难度)
Nuitka
nuitka则是将python源码转成C++(这里得到的是二进制的pyd文件,防止了反编译),然后再编译成可执行文件。
安装:
pip install -U nuitka
安装MinGW64:
Windows环境需安装MinGW64,搭建gcc编译环境
MacOS环境不需要单独下载,它会在安装nuitka时自动下载gcc
下载地址:https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/
打包:
nuitka --mingw64 xxx.py # 单纯打包
nuitka --mingw64 --standalone --show-progress --show-memory --enable-plugin=pyqt5 --output-dir=out demo.py # 指定参数打包
选项说明:
--mingw64:环境选择
--standalone:是否独立环境
--show-progress:展示过程
--show-memory:显示内存
--plugin-enable=qt-plugins:qt配置
--include-qt-plugins=sensible,styles:qt样式保持
--recurse-all:导入引入的资源
nuitka打包并不像网上说的那样,打包速度快,打包体积小。我也实测过,目前体检的感觉就是资源方面的确不用我们考虑那么深,不像pyinstaller可能相关配置就弄好了,打包还是会报资源缺失。而且打包的速度比较慢,体积也挺大的,但是毕竟也是可达到保护Python程序的目的,给使用者方便。
3.代码Obfuscator混淆
借助oxyry在线网站实现obfuscator混淆
在线地址:https://pyob.oxyry.com/
使用 pyobfuscate 库进行混淆
pyobfuscate 会对代码中用户定义的类、函数、变量等进行重命名、更改代码缩进(默认1)、移除注释、添加不影响逻辑的代码语句,最终起到混淆的作用。不过 pyobfuscate 使用 Python2 编写,无法解析 Python3 中的 f-string 等特殊语法,因此使用前需要将源码进行一定程度的修改,当然也可以直接修改 pyobfuscate 库,增加对 Python3 版本的支持。
python pyobfuscate.py demo.py > demo_obfuscated.py
两种主要都是对类和函数名等进行了重置替换,增加阅读难度
4.使用 Cython
使用Cython进行开发
编写文件hello.pyx或hello.py:
def hello():
print('hello')
编写setup.py:
from distutils.core import setup
from Cython.Build import cythonize
setup(name='Hello World app',
ext_modules=cythonize('hello.pyx'))
编译为.c,再进一步编译为.so或.pyd:
python setup.py build_ext --inplace
python -c "from hello import hello;hello()" # 即可直接引用生成的二进制文件中的hello()函数。
生成的二进制 .so 或 .pyd 文件难以破解同时带来了性能提升
5.PyArmor
PyArmor 是一个用于加密和保护 Python 脚本的工具。它能够在运行时刻保护 Python脚本的二进制代码不被泄露,设置加密后 Python 源代码的有效期限,绑定加密后的Python源代码到硬盘、网卡等硬件设备。它的保障机制主要包括:
- 加密编译后的代码块,保护模块中的字符串和常量
- 在脚本运行时候动态加密和解密每一个函数(代码块)的二进制代码
- 代码块执行完成之后清空堆栈局部变量
- 通过授权文件限制加密后脚本的有效期和设备环境
除了对 Python 代码进行加密,PyArmor 还能设置 Python 程序的许可方式,比如设置程序的使用期限、设置允许运行的设备、扩展其他认证方式等
安装:
pip install pyarmor
使用 obfuscate 选项对代码进行加密:
pyarmor obfuscate demo.py
使用 licenses 选项生成许可文件:
pyarmor licenses \
--expired "2023-03-11" \
--bind-disk "10030SFTUF3NJ5T" \
--bind-mac "56:f1:a7:64:f0:64" \
--bind-ipv4 "211.110.6.54" \
r001
使用 pack 选项即可打包脚本:
pyarmor pack demo.py
不过这款工具属于试用阶段,倾向于商业模式,可以学习试试。
以上5种方式都可提升程序的安全性,保护项目敏感信息。如果对外发布的,也可提升破解难度。今天的分享就到这里了,欢迎留言讨论。
相关推荐
- 面试官:来,讲一下枚举类型在开发时中实际应用场景!
-
一.基本介绍枚举是JDK1.5新增的数据类型,使用枚举我们可以很好的描述一些特定的业务场景,比如一年中的春、夏、秋、冬,还有每周的周一到周天,还有各种颜色,以及可以用它来描述一些状态信息,比如错...
- 一日一技:11个基本Python技巧和窍门
-
1.两个数字的交换.x,y=10,20print(x,y)x,y=y,xprint(x,y)输出:102020102.Python字符串取反a="Ge...
- Python Enum 技巧,让代码更简洁、更安全、更易维护
-
如果你是一名Python开发人员,你很可能使用过enum.Enum来创建可读性和可维护性代码。今天发现一个强大的技巧,可以让Enum的境界更进一层,这个技巧不仅能提高可读性,还能以最小的代价增...
- Python元组编程指导教程(python元组的概念)
-
1.元组基础概念1.1什么是元组元组(Tuple)是Python中一种不可变的序列类型,用于存储多个有序的元素。元组与列表(list)类似,但元组一旦创建就不能修改(不可变),这使得元组在某些场景...
- 你可能不知道的实用 Python 功能(python有哪些用)
-
1.超越文件处理的内容管理器大多数开发人员都熟悉使用with语句进行文件操作:withopen('file.txt','r')asfile:co...
- Python 2至3.13新特性总结(python 3.10新特性)
-
以下是Python2到Python3.13的主要新特性总结,按版本分类整理:Python2到Python3的重大变化Python3是一个不向后兼容的版本,主要改进包括:pri...
- Python中for循环访问索引值的方法
-
技术背景在Python编程中,我们经常需要在循环中访问元素的索引值。例如,在处理列表、元组等可迭代对象时,除了要获取元素本身,还需要知道元素的位置。Python提供了多种方式来实现这一需求,下面将详细...
- Python enumerate核心应用解析:索引遍历的高效实践方案
-
喜欢的条友记得关注、点赞、转发、收藏,你们的支持就是我最大的动力源泉。根据GitHub代码分析统计,使用enumerate替代range(len())写法可减少38%的索引错误概率。本文通过12个生产...
- Python入门到脱坑经典案例—列表去重
-
列表去重是Python编程中常见的操作,下面我将介绍多种实现列表去重的方法,从基础到进阶,帮助初学者全面掌握这一技能。方法一:使用集合(set)去重(最简单)pythondefremove_dupl...
- Python枚举类工程实践:常量管理的标准化解决方案
-
本文通过7个生产案例,系统解析枚举类在工程实践中的应用,覆盖状态管理、配置选项、错误代码等场景,适用于Web服务开发、自动化测试及系统集成领域。一、基础概念与语法演进1.1传统常量与枚举类对比#传...
- 让Python枚举更强大!教你玩转Enum扩展
-
为什么你需要关注Enum?在日常开发中,你是否经常遇到这样的代码?ifstatus==1:print("开始处理")elifstatus==2:pri...
- Python枚举(Enum)技巧,你值得了解
-
枚举(Enum)提供了更清晰、结构化的方式来定义常量。通过为枚举添加行为、自动分配值和存储额外数据,可以提升代码的可读性、可维护性,并与数据库结合使用时,使用字符串代替数字能简化调试和查询。Pytho...
- 78行Python代码帮你复现微信撤回消息!
-
来源:悟空智能科技本文约700字,建议阅读5分钟。本文基于python的微信开源库itchat,教你如何收集私聊撤回的信息。[导读]Python曾经对我说:"时日不多,赶紧用Python"。于是看...
- 登录人人都是产品经理即可获得以下权益
-
文章介绍如何利用Cursor自动开发Playwright网页自动化脚本,实现从选题、写文、生图的全流程自动化,并将其打包成API供工作流调用,提高工作效率。虽然我前面文章介绍了很多AI工作流,但它们...
- Python常用小知识-第二弹(python常用方法总结)
-
一、Python中使用JsonPath提取字典中的值JsonPath是解析Json字符串用的,如果有一个多层嵌套的复杂字典,想要根据key和下标来批量提取value,这是比较困难的,使用jsonpat...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python自定义函数 (53)
- python进度条 (67)
- python吧 (67)
- python字典遍历 (54)
- python的for循环 (65)
- python格式化字符串 (61)
- python串口编程 (60)
- python读取文件夹下所有文件 (59)
- java调用python脚本 (56)
- python操作mysql数据库 (66)
- python字典增加键值对 (53)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python人脸识别 (54)
- python多态 (60)
- python命令行参数 (53)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)