用Python写脚本很方便,但是需要特定的python环境才能运行,所以如果你想在其他电脑上运行,就会有很多问题,即使你安装了Python,但是版本可能差别比较大,没有安装相关的依赖库,无法正常运行。有没有什么工具可以把我们写的代码、依赖库和编译环境打包在一起呢?答案是肯定的,Pyinstaller是一个很好的工具,可以一键将你的代码打包成exe文件。先来说说如何使用pyinstaller。一、用Pyinstaller打包python代码1、安装Pyinstaller安装过程非常简单,只需在命令行运行:pipinstallpyinstaller即可完成安装。2.打包代码我写了一个简单的代码作为例子。为了更清楚地演示打包过程,我把main()函数写在了一个单独的文件中,并将mylib.py作为库导入。#mylib.py#importtimedefmyfunc():now=time.time()timetime_str=time.strftime("%Y-%m-%d%H:%M",time.localtime(now))print('现在'+time_str)print("Haveaniceday!")#main.py#importmylibimportosif__name__=="__main__":mylib.myfunc()os.system('pause')这时候只需要在命令行运行:pyinstaller.exe-Fyourcode.py就可以了。会看到一下输出:PSD:\文档\tmp\test>pyinstaller.exe-Fmain.py580INFO:PyInstaller:3.6582INFO:Python:3.7.3585INFO:Platform:Windows-10-10.0.18362-SP0592INFO:wroteD:\文档\tmp\test\main.spec596INFO:UPXisnotavailable.611INFO:ExtendingPYTHONPATHwithpaths['D:\\文档\\tmp\\test','D:\\文档\\tmp\\test']612INFO:checkingAnalysis614INFO:BuildingAnalysisbecauseAnalysis-00.tocisnonexistent614INFO:初始化模块依赖图...620INFO:缓存模块graphhooks...657INFO:Analyzingbase_library.zip...13893INFO:缓存模块依赖图...14161INFO:runningAnalysisAnalysis-00.toc14233INFO:AddingMicrosoft.Windows\Common-Controltodependentassembliesofffiledpythonrequiredbydpyd:exe15748INFO:AnalyzingD:\文档\tmp\test\main.py15751INFO:Processingmodulehooks...15752INFO:Loadingmodulehook"hook-encodings.py"...16003INFO:Loadingmodulehook"hook-pydoc.py"...16011INFO:Loadingmodulehook"hook"-xml.py"...16916INFO:LookingforctypesDLLs16917信息:分析运行时挂钩...16925信息:Lookingfordynamiclibraries17373信息:Lookingforeggs17374信息:使用Python库d:\programfiles\python\python37.dll17374信息:Foundbindingredirects:[]17377INFO:WartxningswrittentoD:\文档nFO\main4.main4.in7.main1.tmp7Graphcross-referencewrittentoD:\文档\tmp\test\build\main\xref-main.html17506INFO:checkingPYZ17507INFO:BuildingPYZbecausePYZ-00.tocisnonexistent17508INFO:BuildingPYZ(ZlibArchive)D:\文档\tmp\test\build\main\PYZ-00。pyz18600INFO:BuildingPYZ(ZlibArchive)D:\文档\tmp\test\build\main\PYZ-00.pyzcompletedsuccessfully.18637INFO:checkingPKG18639INFO:BuildingPKG因为PKG-00.tocis不存在18640INFO:BuildingPKG(CArchive)PKG-00.pkgiveKG22PKG-00.pkg22-00.pkgcompletedsuccessfully.22332INFO:Bootloaderd:\programfiles\python\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe22334INFO:checkingEXE22335INFO:BuildingEXEbecauseEXE-00.tocisnonexistent22336INFO:BuildingEXEfromEXE-01.toc22446信息:将存档附加到EXED:\Documents\tmp\test\dist\main.exe22641信息:从EXE-00.toc成功构建EXE。你将在当前文件夹中看到以下文件:D:.│main.py│main.spec│mylib.py├─build│└─main│Analysis-00.toc│base_library.zip│EXE-00.toc│main.exe.manifest│PKG-00.pkg│PKG-00.toc│PYZ-00.pyz│PYZ-00.toc│warn-main.txt│xref-main.html└─distmain.exe其中,dist文件夹是生成的exe文件,直接双击exe文件即可正常运行。但是这篇文章的重点不是介绍如何使用pyinstaller。此时我又在想,这么简单的打包过程安全吗?打包后的exe文件会不会很容易被反编译?查阅了相关资料后,发现确实可以。二、pyinstaller的反编译过程1、下载并使用pyinstxttractor解压第一步我们用到的工具是pyinstxttractor.py,它可以将pyinstaller生成的exe文件解压成一个pyc文件。项目地址:https://sourceforge.net/projects/pyinstallerextractor/之后把这个文件复制到要解压的exe同级目录下,运行如下命令:pythonpyinstxttractor.pyxx.exe生成一个xx.exe_extracted文件夹运行后,里面包含了一个Heapdll、pyd等文件,需要注意的是里面有一个xxx.exe.manifest文件,xxx可能和你的exe文件名不一样,但这是它的真实名字。然后找到一个没有后缀名为xxx的文件,其实就是你之前打包的.py文件对应的pyc文件。我们找到了一个名为xxx的没有后缀的文件。我们还注意到这个目录下有一个PYZ-00.pyz_extracted文件夹,里面有导入的依赖库。当然,我们自己写的mylib.py也在里面。它也是我们反编译的对象。2.反编译pyc文件,找到pyc文件。下一步是解密它。pyc其实是python程序执行过程中产生的缓存文件,我们在直接运行python代码的时候也会看到。这种格式的反编译比较简单,网上有很多工具,甚至还有很多在线工具。这里为了方便,我使用了一个在线工具。附上链接:http://tools.bugscaner.com/decompyle/但是直接上传我们找到的pyc文件,发现无法反编译。是什么原因?我们用十六进制编辑器(网上可以搜一下,我这里用的是wxMEdit)打开这个文件,和之前直接运行py文件生成的pyc文件进行比较。先来看看main.pyc的区别。左边是我们解包的,右边是运行生成的。左边是我们解包的,右边是运行生成的。唯一不同的是少了第一行16字节(称为magicnumber表示python的版本和编译时间),所以我们可以加上。是否正常解析?确实如此,但是如果您没有原始的pyc文件怎么办?让我们再次查看xx.exe_extracted文件夹。你会发现有一个名为struct的文件,我们给它加上后缀.pyc,试着反编译一下。发现反编译成功如下内容:struct的反编译结果表明它的magicnumber是正确的,那么我们只需要复制它的前16个字节就可以了?我们再试一次,完成了!main.py中的内容反编译成功。main.pyc反编译结果同样可以反编译mylib.py等依赖库的内容。不过值得注意的是,网上很多教程都没有提到依赖库和主程序的pyc文件丢失的字节数。不一样!左:结构文件|中间:解压mylib.pyc|右图:正确的pyc文件我们发现不是少了16个字节,而是中间少了4个字节!然后,我们只需要用结构头的16个字节覆盖mylib.pyc的前12个字节。改好后,反编译。mylib.pyc反编译内容反编译成功!但是,汉字被解析为Unicode编码,可以使用相应的工具进行转换。可见pyinstaller打包的exe还是可以比较容易反编译出来的。那么有没有办法加密打包呢?其实pyinstaller本身是支持加密的。下面说说如何加密打包。3、使用pyinstaller对exe进行加密打包。其实只要在打包的时候加上一个key参数,就可以加密pyinstaller.exe-F--key123456xxx.py,但是需要依赖pycrypto这个包,而python一般不会自带这个包。所以我们需要手动安装。1.安装pycrypto包。原来的安装过程应该很简单,通过pip安装即可。pipinstallpycrypto但是安装过程好像是调用VS编译器编译,导致莫名其妙的问题。如果你在安装过程中没有报错,恭喜你,你可以跳过这部分。在网上找了很多解决方案都无济于事,最后在StackOverflow上找到了完美解决这个问题的答案。原答案地址:https://stackoverflow.com/a/46921479/12954728解决方法如下,前提是你的电脑安装了VisualStudio以我的vs2015为例(1)在开始找到VS文件夹菜单,使用managementRunthis"CompatibleToolCommandPrompt"asmember(2)在你的VS安装目录下找到stdint.h文件,最好什么都搜一下(3)输入setCL=-FI"yourpath\stdint.h》设置环境变量(4)然后执行pipinstallpycrypto安装成功2.使用pyinstaller加密打包现在执行以下命令进行加密打包。key后面是key,可以随便输入。pyinstaller.exe-F--key123456xxx.py3。反编译测试下面我们来测试下加密打包后的exe是否可以反编译。再次执行pyinstxtractor.pyPS>pythonpyinstxtractor.py.\main-encrypt.exeimportimp[*]Processing.\main-encrypt.exe[*]Pyinstallerversion:2.1+[*]Pythonversion:37[*]Lengthofpackage:5787283bytes[*]Found63filesinCArchive[*]开始提取...请待命[+]可能的入口点:pyiboot01_bootstrap[+]可能的入口点:main[*]在PYZarchive中找到136个文件[!]错误:无法解压加密,可能已加密。正在解压。[!]错误:无法解压加密。密码,可能已加密。正在解压。[!]]错误:无法解压缩__future__,可能已加密。正在提取asis。[!]错误:无法解压缩_compat_pickle,可能已加密。正在提取asis。[!]错误:无法解压缩argparse,可能已加密。正在提取asis。[!]错误:无法解压缩st,可能已加密。正在提取asis。[!]错误:无法解压缩加密基4,probledprocryptablyb.Extractingasis.[!]Error:Failedtodecompressbdb,probablyencrypted.Extractingasis.[!]Error:Failedtodecompressbisect,probablyencrypted.Extractingasis.[!]错误:无法解压缩bz2,可能已加密。正在提取asis。[!]错误:无法解压缩日历,可能已加密。正在提取asis。[!]错误:无法解压缩cmd,可能已加密。正在提取asis。[!]错误:无法解压缩代码,可能已加密。正在提取asis。[!]错误:无法解压缩codeop,可能是加密的。Extractingasis。这次下面输出了一长串Error,看来确实加密了。我们再看一下文件夹。main-encrypt.exe_extracted文件夹里面貌似没什么变化,但是PYZ-00.pyz_extracted文件夹里面全是加密文件,应该是反编译不了的。但是,对外部文件夹中的主文件执行相同的操作后,仍然可以反编译源代码。看来这个加密只是针对依赖库的。4.总结如果不想让别人得到你的源码,建议把你程序的入口函数写在一个单独的文件中,然后用加密的方式打包成exe。这样即使别人试图反编译,也只能得到你的入口函数。
