将 exe 文件反编译成 Python 脚本
近期阅读了一篇很感兴趣的文章,为免后续文章被删无法再阅读,现自己写一下哈~
原文章:爆强!将 exe 文件反编译成 Python 脚本!
这篇文章跟自己的另一篇文章,正好形成技术上的互逆过程,也同时欢迎阅读指正
python代码文件封装为可执行exe文件_py_IA&IM的博客-CSDN博客1.安装依赖库pip install pywin32pipinstall pyinstaller(安装失败可换为:pipinstall pyinstaller --no-use-pep517)或可通过python第三方库网站下载后安装。验证pyinstaller安装成功:2.python文件生成可执行exe文件windows+R键 -> cmd -> 控制台界面切入python文件所在的目录执行命令:pyinstaller -F python文件名.py,生成..https://blog.csdn.net/qq_40794377/article/details/108425780
————————————————————————————————————————————————————————————
最近遇到了一个问题,自己打包好的exe文件还在,但是Python源文件不知什么时候被误删了。现在想改动一下功能,重写Python脚本工程量也太大了,怎么办?
今天我将教大家如何反编译exe文件,即将自己或别人写好的exe,还原成Python源码。
以最近写Python一键自动整理归类文件为例进行演示,运行所需的代码和文件都会在文末提供给大家。
打包成单文件所使用的命令为:
pyinstaller -Fw --icon=h.ico auto_organize_gui.py --add-data="h.ico;/"
打包成文件夹所使用的命令为:
pyinstaller -w --icon=h.ico auto_organize_gui.py --add-data="h.ico;."
不管是哪种打包方式都会留下一个exe文件。
首先我们需要从exe文件中抽取出其中的pyc文件:
抽取exe中的pyc文件
抽取pyinstaller打包的exe中的pyc文件,提取pyc文件有两种方法:
通过 pyinstxtractor.py 脚本提取pyc文件
通过 pyi-archive_viewer 工具提取pyc文件
脚本提取pyc文件
pyinstxtractor.py 脚本可以在github项目 python-exe-unpacker 中下载,地址:
https://github.com/countercept/Python-exe-unpacker
下载该项目后把其中的pyinstxtractor.py
脚本文件复制到与exe同级的目录。
然后进入exe所在目录的cmd执行:
Python pyinstxtractor.py auto_organize_gui.exe
执行后便得到exe文件名加上_extracted
后缀的文件夹:
对两种打包方式产生的exe提取出的文件结构稍有区别:
工具提取pyc文件
pyi-archive_viewer是PyInstaller自己提供的工具,它可以直接提取打包结果exe中的pyc文件。
详细介绍可参考官方文档:ttps://pyinstaller.readthedocs.io/en/stable/advanced-topics.html#using-pyi-archive-viewer
执行pyi-archive_viewer [filename]
即可查看 exe 内部的文件结构:
pyi-archive_viewer auto_organize.exe
操作命令:
U: go Up one level
O <name>: open embedded archive name
X <name>: extract name
Q: quit
然后可以提取出指定需要提取的文件:
要提取其他被导入的pyc文件,则需要先打开PYZ-00.pyz
:
很显然,使用PyInstaller的pyi-archive_viewer 工具操作起来比较麻烦,一次只能提取一个文件,遇到子模块还需执行一次打开操作。
所以后面我也只使用pyinstxtractor.py 脚本来提取pyc文件。
反编译pyc文件为py脚本
有很多对pyc文件进行解密的网站,例如:
https://tool.lu/pyc/
不过我们直接使用 uncompyle6
库进行解码,使用pip可以直接安装:
pip install uncompyle6
uncompyle6可以反编译.pyc后缀结尾的文件,两种命令形式:
uncompyle6 xxx.pyc>xxx.py
uncompyle6 -o xxx.py xxx.pyc
以前面编码过程中生成的缓存为例进行演示:
uncompyle6 auto_organize.cpython-37.pyc>auto_organize.py
执行后便直接将.pyc文件反编译成Python脚本了:
从编译结果看注释也被保留了下来:
对于不是pyc后缀结尾的文件,使用uncompyle6反编译时会报出 must point to a Python source that can be compiled, or Python bytecode (.pyc, .pyo) 的错误。
所以我们需要先对提取出的内容人工修改后缀:
运行入口pyc文件反编译
对于从pyinstaller提取出来的pyc文件并不能直接反编译,入口运行类共16字节的 magic
和 时间戳
被去掉了。
如果直接进行反编译,例如执行 uncompyle6 auto_organize_gui.exe_extracted/auto_organize_gui.pyc
会报出如下错误:ImportError: Unknown magic number 227 in auto_organize_gui.exe_extracted\auto_organize_gui.pyc
使用支持16进制编辑的文本编辑器查看一探究竟,这里我使用UltraEdit32
:
分别打开正常情况下编译出的pyc和从pyinstaller提取出来的pyc文件进行对比:
可以看到前16个字节都被去掉了,其中前四个字节是magic
,这四个字节会随着系统和Python版本发生变化,必须一致。后四个字节包括时间戳和一些其他的信息,都可以随意填写。
我们先通过UltraEdit32
向pyinstaller提取的文件添加头信息:
选择开头插入16个字节后,只需要替换前4个字节为当前环境下的magic:
然后执行:
uncompyle6 auto_organize_gui.exe_extracted/auto_organize_gui.pyc>auto_organize_gui.py
执行后可以看到文件已经顺利的被反编译:
依赖性pyc文件反编译
考虑再反编译导入的其他依赖文件:
先用UltraEdit32
打开查看一下:
可以看到对于非入口运行的pyc文件是从12字节开始缺4个字节。
这里我们选择第13个字节再插入四个字节即可:
然后再执行:
uncompyle6 auto_organize_gui.exe_extracted/PYZ-00.pyz_extracted/auto_organize.pyc > auto_organize.py
然后成功的反编译出依赖的文件:
代码与原文件几乎完全一致:
批量反编译
如果一个exe需要被反编译的Python脚本只有3个以内的文件,我们都完全可以人工来操作。
但是假如一个exe涉及几十个甚至上百个Python脚本需要反编译的时候,人工操作未免工作量过于巨大,我们考虑将以上过程用Python实现,从而达到批量反编译的效果。
提取exe中的pyc
import os
import sys
import pyinstxtractorexe_file = r"D:/PycharmProjects/gui_project/dist/auto_organize_gui.exe"
sys.argv = ['pyinstxtractor', exe_file]
pyinstxtractor.main()
# 恢复当前目录位置
os.chdir("..")
[*] Processing D:/PycharmProjects/gui_project/dist/auto_organize_gui.exe
[*] Pyinstaller version: 2.1+
[*] Python version: 37
[*] Length of package: 9491710 bytes
[*] Found 984 files in CArchive
[*] Beginning extraction...please standby
[*] Found 157 files in PYZ archive
[*] Successfully extracted pyinstaller archive: D:/PycharmProjects/gui_project/dist/auto_organize_gui.exeYou can now use a Python decompiler on the pyc files within the extracted directory
预处理pyc文件修护校验头
def find_main(pyc_dir):for pyc_file in os.listdir(pyc_dir):if not pyc_file.startswith("pyi-") and pyc_file.endswith("manifest"):main_file = pyc_file.replace(".exe.manifest", "")result = f"{pyc_dir}/{main_file}"if os.path.exists(result):return main_filepyc_dir = os.path.basename(exe_file)+"_extracted"
main_file = find_main(pyc_dir)
main_file
读取从pyz目录抽取的pyc文件的前4个字节作基准:
pyz_dir = f"{pyc_dir}/PYZ-00.pyz_extracted"
for pyc_file in os.listdir(pyz_dir):if pyc_file.endswith(".pyc"):file = f"{pyz_dir}/{pyc_file}"break
with open(file, "rb") as f:head = f.read(4)
list(map(hex, head))
['0x42', '0xd', '0xd', '0xa']
校准入口类:
import shutil
if os.path.exists("pycfile_tmp"):shutil.rmtree("pycfile_tmp")
os.mkdir("pycfile_tmp")
main_file_result = f"pycfile_tmp/{main_file}.pyc"
with open(f"{pyc_dir}/{main_file}", "rb") as read, open(main_file_result, "wb") as write:write.write(head)write.write(b"\0"*12)write.write(read.read())
校准子类:
pyz_dir = f"{pyc_dir}/PYZ-00.pyz_extracted"
for pyc_file in os.listdir(pyz_dir):pyc_file_src = f"{pyz_dir}/{pyc_file}"pyc_file_dest = f"pycfile_tmp/{pyc_file}"print(pyc_file_src, pyc_file_dest)with open(pyc_file_src, "rb") as read, open(pyc_file_dest, "wb") as write:write.write(read.read(12))write.write(b"\0"*4)write.write(read.read())
开始反编译
from uncompyle6.bin import uncompileif not os.path.exists("py_result"):os.mkdir("py_result")
for pyc_file in os.listdir("pycfile_tmp"):sys.argv = ['uncompyle6', '-o',f'py_result/{pyc_file[:-1]}', f'pycfile_tmp/{pyc_file}']uncompile.main_bin()
完整代码下载见文末。
这样我们只需将Python脚本、exe文件和pyinstxtractor.py
脚本文件 放置到同一文件夹下,运行我们的Python脚本。即可反编译exe。
可以看到已经完美的反编译出exe其中的Python脚本:
好了,相信大家已经明白了反编译的原理。那么既然是攻防,如何防止自己打包的exe被反编译呢?
如何防止exe被反编译呢
只需在打包命令后面加上--key
命令即可,例如文章开头的命令可以更换为:
pyinstaller -Fw --icon=h.ico auto_organize_gui.py --add-data="h.ico;/" --key 123456
123456
是你用来加密的密钥,可以随意更换。
该加密参数依赖tinyaes,可以通过以下命令安装:
pip install tinyaes
打包后再次执行反编译:
exe_file = r"D:/PycharmProjects/gui_project/dist/auto_organize_gui.exe"
uncompyle_exe(exe_file, True)
结果只有入口脚本反编译成功,被依赖的脚本均被加密,无法直接被反编译:
可以看到抽取的中间结果变成了.pyc.encrypted
格式,无法直接被反编译:
可以看到,常规手段就无法直接反编译了。
这个时候还想反编译就需要底层的逆向分析研究了,或者pyinstaller的源码完整研究一遍,了解其加密处理的机制,看看有没有破解的可能。
将 exe 文件反编译成 Python 脚本相关推荐
- Python代码封装的可执行exe文件反编译为Py脚本
起因是笔者有个课,教图形图像学,作业的代码调不出老师的效果,于是就又有了hack的想法,把老师给的用来演示的exe文件反编译.主要是根据这篇文章的方法来的.将 exe 文件反编译成 Python 脚本 ...
- 【干货】Python文件打包 .exe文件反编译
一.Python文件 打包 成 .exe 可执行文件 第一步:安装pyinstaller 首先安装pyinstall,使用命令:pip3 install pyinstaller,当然有可能报错,如下图 ...
- python编译成exe和exe反编译成python
先看文章概要.再看左侧目录,可准确找到需要内容 文章概要:python文件可编译成exe文件,exe文件也可通过反编译恢复为python文件.下面简单介绍如何生成exe和恢复python python ...
- 什么是pyc文件,把python的py文件编译成pyc文件,把pyc文件反编译成py文件。以及python编译的如何设置不生成pyc文件
文章目录 1 什么是pyc文件 1.1 什么是pyc文件 1.2 pyc文件是怎么生成的,有什么好处 2 把python的py文件编译成pyc文件 2.1 使用python内置库py_compile把 ...
- so文件反编译为python代码_【反编译系列】四、反编译so文件(IDA_Pro)
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 安卓应用程序的开发语言是java,但是由于java层的代码很容易被反编译,而反编译c/c++程序的难度比较大,所以现在很多安卓应用程 ...
- apk文件反编译成android代码
文章主要介绍apktool,jd-gui,dex2j的编译步骤,若有其他需要可直接滑到文章最后有自动化工具下载地址.自动化工具不需要代码操作,直接拖动反编译出源代码. 1.Apk反编译步骤 准备工具 ...
- exe4j生成的exe文件反编译
现在网络上越来越流行.net和java写的客户端的小应用程序,而且后缀是exe.本文讨论的是如何从exe4j封装的exe文件中将自己想要的jar抽取出来. exe4j一直是一种比较通用的java ex ...
- linux将py变成exe文件,使用py2exe将Python 脚本生成exe可执行文件
使用Python的py2exe模块可以很容易地帮助我们将Python脚本生成可执行的exe程序.这样我们就可以让脚本脱离虚拟机的束缚,从而独立运行. 环境要求: python虚拟机,我使用的是pyth ...
- exe文件反编译为源文件
准备一个16进制字节码编辑器,UltraEdit 用UltraEdit打开待还原的exe文件,你就会看到这个exe的字节文件. 确定swf的开头,把之前的所有内容全部删除掉. swf大部分都是以46 ...
- s19文件反编译成c语言,S19文件反编译器使用说明.ppt
S19文件反编译器使用说明 S19 decoder Sep 2008 lzbing Decoder Find decoder.exe in codewarrior installation direc ...
最新文章
- 基于OpencvCV的情绪检测
- 【每周CV论文推荐】 初学高效率CNN模型设计应该读的文章
- Python开发【第一篇】:目录
- long long c语言_带你打开C语言的大门之C语言的变量
- Redis系统性介绍
- Android 代码实现查看SQLite数据库中的表
- c语言调用sqlite
- wps表格在拟合曲线找点_excel拟合曲线函数表达式,excel散点拟合出来的公式看不懂。请问怎么写入表格使用?...
- 三容水箱液位控制系统_过程控制实验-三容水箱液位控制系统
- 关于KX混响插件:REVERB R详解
- 保护电路:简单的限流保护电路图
- 使用阿里云接口进行银行卡三四要素实名认证(阿里云api接口java)
- css字的大小,css 中字体大小
- 对Proteus与Keil联调过程中遇到的怪异现象解决方法
- 打开ps显示计算机内存不足怎么办,ps显示内存不足怎么办,教你ps显示内存不足怎么办...
- LICEcap:GIF屏幕录制工具
- 【无线】【流程】QCA无线驱动收包流程分析
- 深度探索:使用FFmpeg实现视频Logo的添加与移除
- node安装后的设置(node_global和node_cache)
- 机器学习-白板推导系列(一)-绪论(机器学习的MLE(最大似然估计)和MAP(最大后验估计))