PyInstaller逆向——解包问题与工具使用

查看 24|回复 3
作者:Jx29   
PyInstaller逆向——解包问题解析与工具使用
本文主要记录解包 PyInstaller 打包文件时遇到的问题及工具的使用方法,相当于对网上教程的一个总结,不涉及反混淆等高级逆向技术。
1. PyInstaller 解包
1.1 pyinstxtractor.py
使用方法:在终端中执行python pyinstxtractor.py ​
注:执行时如果提示python版本问题,需要使用正确的python版本执行。


image-20250523134721-oj7lms6.png (107.28 KB, 下载次数: 0)
下载附件
2025-5-23 18:26 上传

1.2 pyinstxtractor-ng

这个项目是 pyinstxtractor 的一个分支。
pyinstxtractor-ng 使用 xdis 库来解包 Python 字节码,因此不需要使用用于构建可执行文件的相同 Python 版本。
Pyinstxtractor-ng 还支持自动解密加密的 pyinstaller 可执行文件。

使用方法:
$ pyinstxtractor-ng
在线使用:PyInstaller Extractor WEB
1.3 pyinstaller-repacker
使用方法:
$ python pyinst-repacker.py extract
注意:①执行前请确保安装了 lxmllief 依赖,可以使用pip安装pip install lxml lief -i https://pypi.tuna.tsinghua.edu.cn/simple
②仅限 Python 3,不支持加密的 PYZ
③建议使用打包文件使用的python版本执行
另外,此项目还提供了重新打包的功能,在终端中执行:python pyinst-repacker.py build ​
(可选)使用--scanpy​参数来使用相应的 .py 文件,而不是已经存在的 .pyc 文件
$ python pyinst-repacker.py build --scanpy test.exe-repacker
(可选)使用--ignore-missing​参数可在构建期间用于忽略任何不存在的文件,在删除某些文件后尝试重建时很有用。
$ python pyinst-repacker.py build test.exe-repacker
2. pyc文件编译与反编译
2.1 pyc反编译

  • 在线反编译网站:
  • 在线Python pyc文件编译与反编译(3.9以下成功率较高)
  • PyLingual(不会像pycdc那样注明哪里没有反编译成功,有时会缺失一部分代码)

  • 本地反编译工具:
  • Decompyle++(pycdc和pycdas)
  • Pylingual(不支持windows)
  • uncompyle6(可直接pip install,对3.9以上的支持性不好)


    本地反编译pyc的操作方法大致相同:
    $ uncompyle6 -o test.py test.pyc
    $ pycdc test.pyc > test.py
    $ pycdas test.pyc > test.txt #转为字节码
    2.2 py编译为pyc
    使用py_compile编译
    $ python -m py_compile test.py

    $ python -m compileall
    3. Pyinstaller重打包

  • 如果是用pyinstxtractor-ng解包的,需要将解包目录下PYZ-00.pyz_extracted​文件夹里的文件全部复制到上一级文件夹然后通过
    Pyinstaller -F -w ​打包

  • pyinstaller-repacker的重打包方法见上

    4.实战
    4.1 第一个程序


    image-20250523173333-vk87huq.png (18.08 KB, 下载次数: 0)
    下载附件
    2025-5-23 18:29 上传

    首先使用pyinstxtractor-ng解包:


    image-20250523173245-rgp2pgj.png (50.36 KB, 下载次数: 0)
    下载附件
    2025-5-23 18:30 上传

    进入解包文件夹:


    image-20250523173445-m2ocgli.png (155.84 KB, 下载次数: 0)
    下载附件
    2025-5-23 18:29 上传

    将PYZ.pyz_extracted文件夹里的文件全部无脑复制到上一级文件夹里
    尝试直接运行main.pyc,观察是否缺少环境


    image-20250523173714-nbu1lrg.png (13.52 KB, 下载次数: 0)
    下载附件
    2025-5-23 18:30 上传

    运行成功!现在可以进行反编译操作了
    打开PyLingual网站,将main.pyc拖入
    得到反编译后的代码:
    # Decompiled with PyLingual (https://pylingual.io)
    # Internal filename: main.py
    # Bytecode version: 3.12.0rc2 (3531)
    # Source timestamp: 1970-01-01 00:00:00 UTC (0)
    import tkinter as tk
    from tkinter import messagebox
    CORRECT_USERNAME = 'test'
    CORRECT_PASSWORD = '123456'
    def login():
        username = entry_username.get()
        password = entry_password.get()
        if username == CORRECT_USERNAME and password == CORRECT_PASSWORD:
            root.destroy()
            open_main_window(username)
        else:
            messagebox.showerror('登录失败', '用户名或密码错误!')
    def open_main_window(username):
        main_window = tk.Tk()
        main_window.title(f'欢迎, {username}')
        main_window.geometry('400x300')
        label_welcome = tk.Label(main_window, text=f'欢迎回来, {username}!', font=('Arial', 16))
        label_welcome.pack(pady=20)
        label_info = tk.Label(main_window, text='这是您的主界面', font=('Arial', 12))
        label_info.pack(pady=10)
        btn_exit = tk.Button(main_window, text='退出', command=main_window.quit, bg='red', fg='white')
        btn_exit.pack(pady=20)
        main_window.mainloop()
    root = tk.Tk()
    root.title('登录')
    root.geometry('300x200')
    label_title = tk.Label(root, text='用户登录', font=('Arial', 14))
    label_title.pack(pady=10)
    label_username = tk.Label(root, text='用户名:')
    label_username.pack()
    entry_username = tk.Entry(root)
    entry_username.pack()
    label_password = tk.Label(root, text='密码:')
    label_password.pack()
    entry_password = tk.Entry(root, show='*')
    entry_password.pack()
    btn_login = tk.Button(root, text='登录', command=login, bg='blue', fg='white')
    btn_login.pack(pady=20)
    root.mainloop()
    可以看到用户名和密码,很简单吧
    重打包就不演示了
    4.2 第二个程序
    这个程序是我很久之前弄的了,这里就简单说下逆向过程中遇到的问题
    ①确定python版本
    使用“安全分析工具”找到运行中的程序,快速确定具体python版本


    image-20250523175803-tlpzi1b.png (224.78 KB, 下载次数: 0)
    下载附件
    2025-5-23 18:30 上传

    ②重打包不全


    image-20250523180811-qiw23z3.png (62.61 KB, 下载次数: 0)
    下载附件
    2025-5-23 18:30 上传

    可以尝试用以下脚本打包pyinstaller main.spec​,报错少了哪个模块就往里面加那个模块
    import os
    import sys
    block_cipher = None
    script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
    a = Analysis(
        ['main.py'],
        pathex=[script_dir],
        binaries=[],
        datas=[("tkinter", "tkinter")],
        hiddenimports=[
            #在这里添加模块,缺什么就加什么
            'tkinter',
            'platform',
            'inspect'
        ],
        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=False,
        disable_windowed_traceback=False,
        argv_emulation=False,
        target_arch=None,
        codesign_identity=None,
        entitlements_file=None,
    )

    下载次数, 文件

  • dxaw24588   

    好像是高版本的不能还原了嘛
    天业电子   

    支持  正好也在研究  看看
    Jx29
    OP
      


    dxaw24588 发表于 2025-5-23 19:32
    好像是高版本的不能还原了嘛

    是的,高版本python反编译会缺失一部分代码
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部