ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从零实战 Python EXE 逆向工程:用 python-exe-unpacker 把打包源码一步步挖出来

从零实战 Python EXE 逆向工程:用 python-exe-unpacker 把打包源码一步步挖出来 从零实战 Python EXE 逆向工程用 python-exe-unpacker 把打包源码一步步挖出来【免费下载链接】python-exe-unpackerA helper script for unpacking and decompiling EXEs compiled from python code.项目地址: https://gitcode.com/gh_mirrors/py/python-exe-unpacker上周一个没头没尾的 Windows 程序被丢到了我桌上没有文档、没有源码、作者失联。我用十六进制编辑器翻到眼酸最后意识到这是用 Python 打包的可执行文件。这时候python-exe-unpacker 派上了用场——它专门解包 PyInstaller、py2exe 生成的 EXE把里面的 Python 字节码还原成接近源码的可读代码。从拿到文件到源码摊开在屏幕上前后不到十分钟。这篇文章就沿着我这次真实的折腾过程来写。你不需要任何逆向基础跟着走一遍下次遇到类似的 exe 就不会再干瞪眼了。事情要从一个没头没尾的 exe 说起那个小工具界面早就过时了但里面的核心算法还经常被同事用到。作者联系不上只有 exe 孤零零躺在共享盘里。我的任务是搞清楚它内部到底怎么算的。一开始我挺乐观——不就是个 exe 嘛直接看二进制不就行了结果自然是碰了一鼻子灰。硬啃二进制失败后我盯上了打包痕迹用文本方式打开文件全是乱码用 strings 扫一遍倒是蹦出来一堆python27.dll、PyInstaller之类的字样。看到这些我基本可以断定这不是用 C/C 写的原生程序而是用 Python 写完后用打包工具封装起来的。这里先插一句最核心的原理所谓打包就是把你写的.py源码编译成字节码.pyc再把解释器、依赖库、资源文件一起塞进一个自解压的包里。平时我们能看到的只是这个包裹真正的逻辑藏在里面。所以想要源码就得先拆包裹——这正是逆向工具存在的意义也是解包这个动作的由来。第一次上手克隆项目装依赖跑通第一条命令我找到了 python-exe-unpacker 这个开源项目。它本质上是一个工具链的胶水层先识别文件是 PyInstaller 还是 py2exe 打的包再调用对应的提取器和反编译引擎最后把结果整理好交给你。主入口脚本是 python_exe_unpack.pyPyInstaller 的提取核心在 pyinstxtractor.py完整说明可以看项目里的 README.md。上手很简单三步走git clone https://gitcode.com/gh_mirrors/py/python-exe-unpacker cd python-exe-unpacker pip install -r requirements.txt依赖装好后直接对目标文件开刀python python_exe_unpack.py -i mystery_tool.exe一条命令自动判断 PyInstaller 还是 py2exe屏幕上会先打印当前 Python 版本然后脚本开始自己判断文件是 py2exe 打包还是 PyInstaller 打包它会去读 PE 文件的资源段、检查 PyInstaller 归档的签名就是那个著名的 MEI 魔数然后自动走对应的分支全程不用我手动指定格式。这一步体验相当省心比拿着一堆工具逐个试要快太多了。 解包成功但宝藏藏在一个没有扩展名的文件里运行结束后当前目录下多出一个以_extracted结尾的文件夹PyInstaller 包里的所有成员都被拆出来了DLL、依赖库、资源文件……一眼望去密密麻麻。别慌找主逻辑有个窍门PyInstaller 打包的程序主入口脚本通常是没有扩展名的那个文件。在mystery_tool.exe_extracted里我看到一堆.pyd、.dll唯独一个名叫mystery_tool的文件干干净净没有后缀大小也只有几百字节——就是它了。这个文件本质是一份 PYC 字节码按理说可以直接用 uncompyle6 反编译。可我兴冲冲试了一下反编译引擎直接报错于是进入了第一个坑。第一个坑缺了魔术数的 PYC 怎么救查了 README 才知道这是逆向 PyInstaller 文件的经典问题主入口文件在被塞进归档时头部的魔术数magic number用于标识 Python 版本的关键字节被剥掉了。没有它反编译工具根本认不出这是什么版本的字节码。解决办法很简单python-exe-unpacker 专门留了一个参数python python_exe_unpack.py -p mystery_tool-p会先检测文件头部如果缺魔术数就自动补上然后直接调用 uncompyle6 反编译。运行完同目录多了一个mystery_tool.py——打开一看注释、字符串、函数逻辑清清楚楚。那一刻的成就感不比解开一个迷宫差。第二个坑撞上加密字节码怎么办本来以为到此为止了结果第二个文件给了我一个惊喜PyInstaller 打包时可以选择加密字节码把.pyc用 AES 加密后再塞进归档。直接反编译出来的全是密文毫无意义。好在工具内置了对这种情况的处理。运行时它发现了密钥线索——一个名为pyimod00_crypto_key的文件于是弹出一句询问[*] Encrypted pyc file is found. Decrypt it? [y/n]输入y它会自动把密钥文件反编译出来、提取真正的 AES 密钥然后逐一对加密的字节码解密最后统一反编译成源码。整个过程黑盒完成我只负责按一个键。原理上它参考了社区公开的加密 PyInstaller 提取研究把逆 AES 的复杂操作封装成了命令行省去了手动分析的功夫。第三个坑版本不兼容报错先别急着砸电脑正当我得意的时候第三个 exe 又给我上了一课。这次是 py2exe 格式结果脚本报出这样一行Error in unpacking the exe. Probably due to version incompatibility (exe created using python 2 and run this script with python 3)原因很典型py2exe 的解包依赖 Python 的 marshal 模块而 Python 2 和 Python 3 对字节码的序列化格式不一样。目标文件是老 Python 2 打的包我却用 Python 3 跑脚本自然对不上。解决办法就是用同一时代的工具换一个与打包环境匹配的 Python 版本重跑比如python2 python_exe_unpack.py -i old_legacy.exe反过来也一样Python 3 打的包尽量用 Python 3 环境。工具作者在 README 里明确提示过这个坑遇到它先检查版本往往比查半天代码更管用。举一反三一次分析一堆文件理顺流程之后我发现这套东西完全可以批量使用。比如要分析一个文件夹下的十几个 exe写个简单循环就行for f in *.exe; do python python_exe_unpack.py -i $f done对安全研究人员来说这种批量解包很适合做样本初筛先把源码都掏出来再决定哪些值得深入分析。py2exe 的文件解包结果默认放在unpacked目录下也可以用-o参数指定输出位置方便归档管理。打包与解包其实是一对镜像操作回头总结整个过程一句话就能说清打包是把源码藏进一个自解压包里解包就是沿着打包的路径一步步走回去。python-exe-unpacker 替你走完了识别格式 → 拆归档 → 修头信息 → 反编译这四步把原本繁琐的逆向工作压缩成一条命令。当然它也不是万能的。目前主要支持 PyInstaller 和 py2exe 两种打包格式如果目标文件用了新版打包器、复杂混淆或者动态生成代码还原出来的代码质量会打折扣甚至直接失败。另外Python 版本必须尽量对齐这是所有 Python 逆向工具的通病。⚠️ 最后两句掏心窝的提醒工具好用但请记住边界只解包你有权分析的文件。分析自己的软件、做合规的安全研究、学习开源生态里的样本都没问题但未经授权拆解他人的商业软件既可能侵权也可能触犯法律。能力越大越要管住手。另外如果哪天你遇到一个解不开的 exe别急着怀疑工具坏了——先确认 Python 版本对不对、文件是否完整、依赖是否装齐八成问题出在这三件事上。现在轮到你动手了我已经帮你把整条路踩平了克隆项目、装依赖、跑-i解包、用-p修魔术数、遇到加密就按y、版本不对就换解释器。剩下的就是找一个你自己写的或者有权限分析的Python 程序用 PyInstaller 打一个包再亲手把它解回来。相信我当你在终端看到自己亲手写的代码被原样挖出来的那一刻你会彻底理解 Python 打包机制也会对逆向工程上瘾。现在就打开终端跑出你的第一个解包结果吧。【免费下载链接】python-exe-unpackerA helper script for unpacking and decompiling EXEs compiled from python code.项目地址: https://gitcode.com/gh_mirrors/py/python-exe-unpacker创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表