其实一般的程序安全上只需要两步就行,没必要再加密改解释器等,已经不可能反编译到原有python了,因为动态链接库就是汇编了,中间经历了python转c,c在转动态库,代码已经没有可读性了。但是一些密码等重要字符还是要处理好,如分割存储密码,多次转换等。
(1)cython 编译为动态链接库(linux为so,windows为pyd)即可。
(2)然后再用pyinstaller与打包为exe,可以压缩一下,参考https://liuhuiyao.blog.csdn.net/article/details/81236642
过程
目录结构
main中import aaa, aaa中import bbb,bbb中 import n.ccc
先获取所有模块名,及模块路径
(也可以考虑合并为一个文件,但代码会作为一个字符串,汇编后不知会不会容易泄露)
获取所有依赖模块名可参考:https://liuhuiyao.blog.csdn.net/article/details/132920782
然后在引用上述代码,编写如下:
if __name__ == '__main__':
mw=ModuleWriterGenerator()
mw.generate_for_file("main.py")
mnames = list()
mpaths=list()
mpaths2=list()
pydRootPath="D:/hahah/test/"#生成的pyd文件根路径
for name in mw._modules:
mnames.append(name)
path=mw._modules[name][0]
if path:
mpaths.append((pydRootPath+path.replace(".py",".cp311-win_amd64.pyd"),"."))
mpaths2.append(path)
print (mnames)#模块名,用于pyinstaller 打包exe中main.spec文件中的binaries属性
print(mpaths) #pyd文件路径,用于pyinstaller 打包exe中main.spec文件中的hiddenimports属性
print(mpaths2)#模块文件路径,可用于Cython转pyd
输出
['json', 'aaa', 'bbb', 'n', 'n.ccc']
[('D:/hahah/test/aaa.cp311-win_amd64.pyd', '.'), ('D:/hahah/test/bbb.cp311-win_amd64.pyd', '.'), ('D:/hahah/test/n/__init__.cp311-win_amd64.pyd', '.'), ('D:/hahah/test/n/ccc.cp311-win_amd64.pyd', '.')]
['aaa.py', 'bbb.py', 'n/__init__.py', 'n/ccc.py']
cython转为pyd
import Cython.Build
import distutils.core
def py_to_pyd(files:list):
cpy = Cython.Build.cythonize(files) # 返回distutils.extension.Extension对象列表
distutils.core.setup(
name='pyd的编译', # 包名称
version="1.0", # 包版本号
ext_modules=cpy, # 扩展模块
author="", # 作者
author_email="" # 作者邮箱
)
if __name__ == '__main__':
files = ['aaa.py', 'bbb.py', 'n/__init__.py', 'n/ccc.py'] # 需要编译的文件
py_to_pyd(files)
pyinstaller打包exe
打包前,先把py,pyc文件,删除或移动到其他目录,防止误打包进去暴漏代码。
pyinstaller -F main.py
执行上述,生成的程序可能无法运行,缺少各种模块或者动态库,需要编辑main.spec描述文件.
pyinstaller可以通过py文件import的方式引入pyd文件,但pyd文件中引入的其他包不会被打包到exe,需要手动指定把哪些pyd打包进去。
改动main.spec文件
先执行完pyinstaller -F main.py命令,会生成一个main.spec文件,修改其中的两个属性如下:
动态库拷贝添加到下面数组中,第一个参数是源文件路径,第二个参数目标路径
binaries=[('D:/hahah/test/aaa.cp311-win_amd64.pyd', '.'), ('D:/hahah/test/bbb.cp311-win_amd64.pyd', '.'), ('D:/hahah/test/n/__init__.cp311-win_amd64.pyd', '.'), ('D:/hahah/test/n/ccc.cp311-win_amd64.pyd', '.')],
缺少的python模块添加到以下数组中,缺哪个补哪个(可以全写上,但把py,pyc文件先删除,防止打包进去暴漏代码)
hiddenimports=['json', 'aaa', 'bbb', 'n', 'n.ccc'],
修改完如下:只改了其中两行
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['main.py'],
pathex=[],
binaries=[('D:/hahah/test/aaa.cp311-win_amd64.pyd', '.'), ('D:/hahah/test/bbb.cp311-win_amd64.pyd', '.'), ('D:/hahah/test/n/__init__.cp311-win_amd64.pyd', '.'), ('D:/hahah/test/n/ccc.cp311-win_amd64.pyd', '.')],
datas=[],
hiddenimports=['json', 'aaa', 'bbb', 'n', 'n.ccc'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
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,
[],
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
编辑完毕后执行如下命令生成程序
pyinstaller main.spec
运行main.exe ,确认没有问题
自己文章参考
https://blog.csdn.net/u013378306/article/details/132908028
https://liuhuiyao.blog.csdn.net/article/details/132920782
https://liuhuiyao.blog.csdn.net/article/details/132907302
https://liuhuiyao.blog.csdn.net/article/details/81236642
别人文章参考:
Cython+Pyinstaller Python编译与打包-踩坑 - 知乎
pyinstaller与cython打包python执行程序_cython pyinstaller_telllong的博客-CSDN博客