想了解Python源代码加密吗?现总结如下5大加密混淆手段!

我们在进行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
图片.png

批量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 -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  选择图标

图片.png

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打包并不像网上说的那样,打包速度快,打包体积小。我也实测过,目前体检的感觉就是资源方面的确不用我们考虑那么深,不像p yin staller可能相关配置就弄好了,打包还是会报资源缺失。而且打包的速度比较慢,体积也挺大的,但是毕竟也是可达到保护Python程序的目的,给使用者方便。

3.代码Obfuscator混淆

借助oxyry在线网站实现obfuscator混淆

在线地址:https://pyob.oxyry.com/

图片.png

使用 pyobfuscate 库进行混淆

pyobfuscate 会对代码中用户定义的类、函数、变量等进行重命名、更改代码缩进(默认1)、移除注释、添加不影响逻辑的代码语句,最终起到混淆的作用。不过 pyobfuscate 使用 Python2 编写,无法解析 Python3 中的 f-string 等特殊语法,因此使用前需要将源码进行一定程度的修改,当然也可以直接修改 pyobfuscate 库,增加对 Python3 版本的支持。

python2 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种方式都可提升程序的安全性,保护项目敏感信息。如果对外发布的,也可提升破解难度。今天的分享就到这里了,欢迎留言讨论。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容