pyinstall 打包python3.7.1的exe反编译

article/2025/10/11 13:14:39

pyinstall 打包python3.7.1的exe反编译

  由于 pyinstall打包的EXE文件,被360认为可能有木马病毒,首先怀疑计算数机系统有毒。用360杀毒,病毒倒是查处了十几个,对于一个对计算机不是十分精通的人来说,只能按360的提示去做,结果造成许多应用程序的快捷键丢失,三搞两搞,系统崩溃,重做系统,一不小心,把python的源文件丢失,半个多月的心血全费(我是刚刚学习python)。不幸中的万幸,单位电脑中有EXE文件,便产生了反编译的念头。我使用的python是3.7.1 ,与网上提供人资料有点不同,反反复复的查月资料,不断实践、改进、探索,基本恢复python的源文件。实践过程如下:第一步:把EXE反编译为pyc文件。根据网上提供的资料,我选了两个文件 archive_viewer.py 和 pyinstxtractor.py反编译exe(由于 archive_viewer.py反编译的文件,最终没能成共把exe反编译为PY),其操作过程就不写了。pyinstxtractor.py        
"""
PyInstaller Extractor v1.9 (Supports pyinstaller 3.3, 3.2, 3.1, 3.0, 2.1, 2.0)
Author : Extreme Coders
E-mail : extremecoders(at)hotmail(dot)com
Web    : https://0xec.blogspot.com
Date   : 29-November-2017
Url    : https://sourceforge.net/projects/pyinstallerextractor/For any suggestions, leave a comment on
https://forum.tuts4you.com/topic/34455-pyinstaller-extractor/This script extracts a pyinstaller generated executable file.
Pyinstaller installation is not needed. The script has it all.For best results, it is recommended to run this script in the
same version of python as was used to create the executable.
This is just to prevent unmarshalling errors(if any) while
extracting the PYZ archive.Usage : Just copy this script to the directory where your exe residesand run the script with the exe file name as a parameterC:\path\to\exe\>python pyinstxtractor.py <filename>
$ /path/to/exe/python pyinstxtractor.py <filename>Licensed under GNU General Public License (GPL) v3.
You are free to modify this source.CHANGELOG
================================================Version 1.1 (Jan 28, 2014)
-------------------------------------------------
- First Release
- Supports only pyinstaller 2.0Version 1.2 (Sept 12, 2015)
-------------------------------------------------
- Added support for pyinstaller 2.1 and 3.0 dev
- Cleaned up code
- Script is now more verbose
- Executable extracted within a dedicated sub-directory(Support for pyinstaller 3.0 dev is experimental)Version 1.3 (Dec 12, 2015)
-------------------------------------------------
- Added support for pyinstaller 3.0 final
- Script is compatible with both python 2.x & 3.x (Thanks to Moritz Kroll @ Avira Operations GmbH & Co. KG)Version 1.4 (Jan 19, 2016)
-------------------------------------------------
- Fixed a bug when writing pyc files >= version 3.3 (Thanks to Daniello Alto: https://github.com/Djamana)Version 1.5 (March 1, 2016)
-------------------------------------------------
- Added support for pyinstaller 3.1 (Thanks to Berwyn Hoyt for reporting)Version 1.6 (Sept 5, 2016)
-------------------------------------------------
- Added support for pyinstaller 3.2
- Extractor will use a random name while extracting unnamed files.
- For encrypted pyz archives it will dump the contents as is. Previously, the tool would fail.Version 1.7 (March 13, 2017)
-------------------------------------------------
- Made the script compatible with python 2.6 (Thanks to Ross for reporting)Version 1.8 (April 28, 2017)
-------------------------------------------------
- Support for sub-directories in .pyz files (Thanks to Moritz Kroll @ Avira Operations GmbH & Co. KG)Version 1.9 (November 29, 2017)
-------------------------------------------------
- Added support for pyinstaller 3.3
- Display the scripts which are run at entry (Thanks to Michael Gillespie @ malwarehunterteam for the feature request)"""from __future__ import print_function
import os
import struct
import marshal
import zlib
import sys
import imp
import types
from uuid import uuid4 as uniquenameclass CTOCEntry:def __init__(self, position, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name):self.position = positionself.cmprsdDataSize = cmprsdDataSizeself.uncmprsdDataSize = uncmprsdDataSizeself.cmprsFlag = cmprsFlagself.typeCmprsData = typeCmprsDataself.name = nameclass PyInstArchive:PYINST20_COOKIE_SIZE = 24           # For pyinstaller 2.0PYINST21_COOKIE_SIZE = 24 + 64      # For pyinstaller 2.1+MAGIC = b'MEI\014\013\012\013\016'  # Magic number which identifies pyinstallerdef __init__(self, path):self.filePath = pathdef open(self):try:self.fPtr = open(self.filePath, 'rb')self.fileSize = os.stat(self.filePath).st_sizeexcept:print('[*] Error: Could not open {0}'.format(self.filePath))return Falsereturn Truedef close(self):try:self.fPtr.close()except:passdef checkFile(self):print('[*] Processing {0}'.format(self.filePath))# Check if it is a 2.0 archiveself.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)magicFromFile = self.fPtr.read(len(self.MAGIC))if magicFromFile == self.MAGIC:self.pyinstVer = 20     # pyinstaller 2.0print('[*] Pyinstaller version: 2.0')return True# Check for pyinstaller 2.1+ before bailing outself.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)magicFromFile = self.fPtr.read(len(self.MAGIC))if magicFromFile == self.MAGIC:print('[*] Pyinstaller version: 2.1+')self.pyinstVer = 21     # pyinstaller 2.1+return Trueprint('[*] Error : Unsupported pyinstaller version or not a pyinstaller archive')return Falsedef getCArchiveInfo(self):try:if self.pyinstVer == 20:self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)# Read CArchive cookie(magic, lengthofPackage, toc, tocLen, self.pyver) = \struct.unpack('!8siiii', self.fPtr.read(self.PYINST20_COOKIE_SIZE))elif self.pyinstVer == 21:self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)# Read CArchive cookie(magic, lengthofPackage, toc, tocLen, self.pyver, pylibname) = \struct.unpack('!8siiii64s', self.fPtr.read(self.PYINST21_COOKIE_SIZE))except:print('[*] Error : The file is not a pyinstaller archive')return Falseprint('[*] Python version: {0}'.format(self.pyver))# Overlay is the data appended at the end of the PEself.overlaySize = lengthofPackageself.overlayPos = self.fileSize - self.overlaySizeself.tableOfContentsPos = self.overlayPos + tocself.tableOfContentsSize = tocLenprint('[*] Length of package: {0} bytes'.format(self.overlaySize))return Truedef parseTOC(self):# Go to the table of contentsself.fPtr.seek(self.tableOfContentsPos, os.SEEK_SET)self.tocList = []parsedLen = 0# Parse table of contentswhile parsedLen < self.tableOfContentsSize:(entrySize, ) = struct.unpack('!i', self.fPtr.read(4))nameLen = struct.calcsize('!iiiiBc')(entryPos, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name) = \struct.unpack( \'!iiiBc{0}s'.format(entrySize - nameLen), \self.fPtr.read(entrySize - 4))name = name.decode('utf-8').rstrip('\0')if len(name) == 0:name = str(uniquename())print('[!] Warning: Found an unamed file in CArchive. Using random name {0}'.format(name))self.tocList.append( \CTOCEntry(                      \self.overlayPos + entryPos, \cmprsdDataSize,             \uncmprsdDataSize,           \cmprsFlag,                  \typeCmprsData,              \name                        \))parsedLen += entrySizeprint('[*] Found {0} files in CArchive'.format(len(self.tocList)))def extractFiles(self):print('[*] Beginning extraction...please standby')extractionDir = os.path.join(os.getcwd(), os.path.basename(self.filePath) + '_extracted')if not os.path.exists(extractionDir):os.mkdir(extractionDir)os.chdir(extractionDir)for entry in self.tocList:basePath = os.path.dirname(entry.name)if basePath != '':# Check if path exists, create if notif not os.path.exists(basePath):os.makedirs(basePath)self.fPtr.seek(entry.position, os.SEEK_SET)data = self.fPtr.read(entry.cmprsdDataSize)if entry.cmprsFlag == 1:data = zlib.decompress(data)# Malware may tamper with the uncompressed size# Comment out the assertion in such a caseassert len(data) == entry.uncmprsdDataSize # Sanity Checkwith open(entry.name, 'wb') as f:f.write(data)if entry.typeCmprsData == b's':print('[+] Possible entry point: {0}'.format(entry.name))elif entry.typeCmprsData == b'z' or entry.typeCmprsData == b'Z':self._extractPyz(entry.name)def _extractPyz(self, name):dirName =  name + '_extracted'# Create a directory for the contents of the pyzif not os.path.exists(dirName):os.mkdir(dirName)with open(name, 'rb') as f:pyzMagic = f.read(4)assert pyzMagic == b'PYZ\0' # Sanity CheckpycHeader = f.read(4) # Python magic valueif imp.get_magic() != pycHeader:print('[!] Warning: The script is running in a different python version than the one used to build the executable')print('    Run this script in Python{0} to prevent extraction errors(if any) during unmarshalling'.format(self.pyver))(tocPosition, ) = struct.unpack('!i', f.read(4))f.seek(tocPosition, os.SEEK_SET)try:toc = marshal.load(f)except:print('[!] Unmarshalling FAILED. Cannot extract {0}. Extracting remaining files.'.format(name))returnprint('[*] Found {0} files in PYZ archive'.format(len(toc)))# From pyinstaller 3.1+ toc is a list of tuplesif type(toc) == list:toc = dict(toc)for key in toc.keys():(ispkg, pos, length) = toc[key]f.seek(pos, os.SEEK_SET)fileName = keytry:# for Python > 3.3 some keys are bytes object some are str objectfileName = key.decode('utf-8')except:pass# Make sure destination directory exists, ensuring we keep inside dirNamedestName = os.path.join(dirName, fileName.replace("..", "__"))destDirName = os.path.dirname(destName)if not os.path.exists(destDirName):os.makedirs(destDirName)try:data = f.read(length)data = zlib.decompress(data)except:print('[!] Error: Failed to decompress {0}, probably encrypted. Extracting as is.'.format(fileName))open(destName + '.pyc.encrypted', 'wb').write(data)continuewith open(destName + '.pyc', 'wb') as pycFile:pycFile.write(pycHeader)      # Write pyc magicpycFile.write(b'\0' * 4)      # Write timestampif self.pyver >= 33:pycFile.write(b'\0' * 4)  # Size parameter added in Python 3.3pycFile.write(data)def main():if len(sys.argv) < 2:print('[*] Usage: pyinstxtractor.py <filename>')else:arch = PyInstArchive(sys.argv[1])if arch.open():if arch.checkFile():if arch.getCArchiveInfo():arch.parseTOC()arch.extractFiles()arch.close()print('[*] Successfully extracted pyinstaller archive: {0}'.format(sys.argv[1]))print('')print('You can now use a python decompiler on the pyc files within the extracted directory')returnarch.close()if __name__ == '__main__':main()

把pyinstxtractor.py 与exe放在同目录下,执行
python pyinstxtractor.py ZkDuibi1.exe(我的应用程序ZkDuibi1.exe)
![在这里插入图片描述]
生成一个Zkduibi1.exe_extracted文件夹。

在这里插入图片描述
可以看红线标出的部分,第一个文件夹是库文件,有系统的,也有自己编写的,好在我编写都是以My_xxx_xxx开,虽然是初次学习反编译,但还是很容易找出了自己编写的文件。第二个文件记录着pyc文件的头信息。第三个文件是自己的pyc文件,只是没有扩展名,可自己家上,到此,反编译第一步(exe-------pyc)完成。
由于pyinstall把py编译为exe时,把pyc文件的头部信息去掉,所以,我们反编译时要动手加入头部信息。
打开第二、第三个文件(我用HXD)

在这里插入图片描述

在这里插入图片描述
比较这俩个文件的头部,发现zkduibi比struct少了十六个字节(据说是版本信息等等,不要搞明白),添加上这十六个字节。
下一步就是把pyc反编译为py,先用网上的在线工具均没成功。
后用uncompyle6 反编译成功!uncompyle6的安装,
pip install uncompyle6
执行uncompyle6 xxxx.pyc > xxx.py即可。
在这里插入图片描述
下一步反编译PYZ-00.pyz_extracted中的文件,用HXD打开文件,与struct比较,发现至少4个字节(以E3为标),增加4个字节(00 00 00 00)(如过不增加这4 个字节,错误如下)
在这里插入图片描述
本想到此,就能顺利完成反编译,结果,有的文件能顺利反编译,有的不能。错误如下
在这里插入图片描述
从图中“GBK”可知,应与编码有关,查阅“\ufffd”是python中不可显示的中文,到底是什么,忽然想起,在编写 py文件时有过怪字符现象。故编写了只有几个怪字符的py文件,用HXD打开,发现怪字符编码为EF BF BD (�),紧接着在用HDX打开反编译出错的文件, 查找EF BF BD (�)替换为可显示字符(任意如 aaa)。存盘,再次反编译成功。
   反编译工作完成!!!


http://chatgpt.dhexx.cn/article/frGLZMDD.shtml

相关文章

pyinstall打包多个.py文件成应用程序

Pyinstall打包多个.py文件成应用程序的方法&#xff1a; 这里成功打包了两个.py文件&#xff0c;一张图片&#xff0c;一个.h5文件 如图所示&#xff1a; 第一步&#xff1a;生成.spec文件 pyinstaller -c -D main.py -p image_handler.py这里main.py文件是主文件&#xff0…

解决python3.6中pyinstall打包失败的问题

环境&#xff1a;python 3.6 pyinstall 一开始用百度上的方法&#xff0c;直接执行python目录下的pyinstall.exe文件&#xff0c;很好用。 C:\WINDOWS\System32>C:\Users\hasee\AppData\Local\Programs\Python\Python36\Scripts\pyinstaller.exe F:\python_code_test\ren…

pyqt5 +pyinstall打造属于自己的桌面版程序(学习阶段)

网上关于pyqt5的教程特别少,终于东拼西凑,做出一点东西出来,很简单的小应用,便于上手学习。 pyqt5的主文件代码如下,代码特别多,也没怎么细分。大家可以参考下。github地址 pyinstall打包的一点小技巧送给大家。 取消生成程序doc窗口使用命令pyinstaller -F -i 图标路径 …

tkinter - 使用Pyinstall进行打包封装

1 需要安装 PyInstaller C:\Users\30818> pip install pyinstaller 2 将模块py文件打包成pyd 防止反编译暴露源代码 pyd是一个模块插件 可以通过 Import 来引入pyd文件 直接编译会提示二进制读取错误 2-1 安装cython pip install cython 2-2 在当前目录创建一个 set…

【踩坑日记(一)】: Pyinstall 打包.py文件 生成exe可执行文件

文章目录 Pyinstall 打包.py文件 生成exe可执行文件如何入坑&出坑Analysis 实例其他实例常用参数参考文档&#xff1a;Pyinstall 官方手册 Pyinstall 打包.py文件 生成exe可执行文件 原本认为很轻松的事情&#xff0c;结果花了近2个小时才搞定&#xff0c;值得记录下踩的坑…

Ubuntu 16.04 安装 Pyinstall

Ubuntu 16.04 安装 Pyinstall 预装环境 python3 version&#xff1a;3.5pip version&#xff1a;8.1 报错如下&#xff1a; 首先直接安装 pyinstall 报错&#xff0c;pip 版本过低&#xff0c;要升级版本使用 提供的命令升级 pip&#xff0c;但是开始套娃&#xff0c;一直循…

pyinstall 打包报错

关于使用pyinstaller 打包报错 我的python安装位置为 安装位置/usr/local/python3 关于我的报错环境属于linux 我的pyinstaller 是使用pip 安装的 pip install pyinstaller 在使用pycharm 打包的时候,报错 打包就告诉我缺少什么 关于python的 iso包 我当时有全磁盘搜索该文…

pyinstall exe打包详解

在学习和工作之中&#xff0c;想制作一些小工具&#xff0c;用python秃了一个晚上&#xff0c;拿到公司&#xff0c;发现要安装python才能用&#xff0c;看别人的博客看不懂&#xff0c;别急&#xff0c;一篇搞定。 一、pyinstaller安装 pyinstaller 是一个python库&#xff0…

pyinstall加密打包

这个工具打包真的是挺省事的&#xff0c;但是一旦涉及保护源码&#xff0c;那么原来简单的打包就不够用了。轻易就能被人反编译。 工具自然也是要进步的&#xff0c;现在pyinstall支持加密打包了。 虽然我没查到他加密的原理是什么&#xff0c;但是应该比原来破解增加了一些难度…

PyInstall的安装,使用,以及最后打包成一个exe文件

首先PyInstall安装 pip3 install pyinstaller -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com 打包常用命令 pyinstaller -w -F test.py -w 表示运行exe文件后不出现cmd命令窗口 -F 表示打包成一个单独的exe文件 使用命令后会生成两个文件夹。 …

WIFI传输速度测试

环境&#xff1a; 1.A电脑共享文件&#xff0c;有线1000M&#xff0c;空载&#xff0c;正常机械硬盘&#xff0c;硬盘速度120M/S 2.B电脑从A拷贝数据&#xff0c;USB1.5米延长线接的网卡&#xff0c;USB2.0&#xff0c;WIFI 5G 600M&#xff0c;空载 3.拷贝文件&#xff0c;阿凡…

诺基亚N1 WIFI感叹号消除

Android Captive Portal Server 安卓系统wifi连接后&#xff0c;与CPS服务器通信&#xff0c;检测是否连接到互联网&#xff0c;当不能默认的CPS时就会有感叹号。 通过ADB设置可以消除这个感叹号。 下好ADB之后&#xff0c;打开ADB文件夹&#xff0c;按住shift鼠标右键&…

WIFI理论速度计算

参考&#xff1a; https://cn.ui.vmall.com/thread-1349237-1-4.html 以下是各个WIFI版本的最大吞吐量表 wifi802.11802.11a802.11b802.11g802.11n802.11ac最大吞吐量(Mbps)25411546006928 强调下&#xff0c;MbpsMbit/s即兆比特每秒&#xff08;1,000,000bit/s&#xff09;不…

Android 修改wifi阀值,6种简单方法使WiFi网络提速

6种简单方法使WiFi网络提速 导语:不给力的WiFi连接使得无线上网给人的感觉像是回到了拨号时代。以下是小编精心整理的有关电脑网络知识,希望对大家有所帮助。 1、升级过时的路由器 并非所有人都愿意花钱解决WiFi网速慢的问题,但许多人都需要这么做。最近数年路由器技术取得了…

WIFI 常识

DSSS (Direct Sequence Spread Spectrum)直接序列扩频 FHSS&#xff0c;跳频技术 (Frequency-Hopping Spread Spectrum) FHSS和DSSS比较 跳频扩频&#xff08;FHSS&#xff09;: 跳频扩频&#xff08;FHSS&#xff09;技术是通过“伪随机码”的调制&#xff0c;信息的载波受…

Win10系统正确设置MTU值加快WIFI速度的方法

MTU是Maximum Transmission Unit缩写&#xff0c;中文名&#xff1a;最大传输单元。 工具/原料 硬件&#xff1a;电脑 操作系统&#xff1a;Windows 10 方法/步骤 第一步&#xff1a;查询自己电脑的MTU值 右键【开始】–【命令提示符(管理员)】&#xff1b; netsh interface …

WiFi的真实速率

“虽然许多路由器厂商宣称自家的路由器可以达到极高的速率&#xff0c;但实际上用户购买回去用起来却很难达到很快的速率。因为WiFi传输速率是符合木桶效应的&#xff0c;许多时候速率受限于接入路由器的WiFi终端性能。只有全链路能够达到的速率&#xff0c;才是使用者感受到的…

esp32测试wifi速率

一、下载demo&#xff0c; demo路径esp-idf\examples\wifi\iperf 注意&#xff1a;运行可能会报分区表错&#xff0c;idf.py menuconfig修改下flash为DIO模式再试&#xff1b; 二、测试 1、上电运行demo&#xff0c;PC和esp32连接同一个wifi热点&#xff1b; 2、执行idf.p…

WIFI6速率

WiFi 6在160MHz信道宽度下&#xff0c;单流最快速率为1201Mbit/s&#xff0c;理论最大数据吞吐量9.6Gbps。跟前五代比一比&#xff1a;第一代 802.11b&#xff08;Wi-Fi 1&#xff09;&#xff0c;最快11Mbit/s第二代 802.11a&#xff08;Wi-Fi 2&#xff09;&#xff0c;最快5…

提高企业WiFi速度的快速简便的方法—Vecloud微云

WiFi已成为必不可少的商业工具。连接缓慢或不可靠都会对员工的工作效率和客户服务产生不利影响。 但是&#xff0c;如何确保充分利用无线互联网解决方案呢&#xff1f; 以下是一些提高组织中的WiFi速度的快速简便的方法。 零成本提升WiFi速度的方法 在考虑附有成本的解决方案…