吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1966|回复: 15
上一主题 下一主题
收起左侧

[PC样本分析] 【逆向复现】PyInstaller简单复现

[复制链接]
跳转到指定楼层
楼主
LovenSar 发表于 2025-4-16 08:48 回帖奖励
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 LovenSar 于 2025-4-16 14:25 编辑

声明

本文为结合网上资料+自己理解+LLM辅助学习的笔记,在解释部分为AI生成内容,复现部分截图为本人复现过程。

一句话概括

基于Python打包的exe恶意软件通常是通过将恶意代码隐藏在看似正常的Python脚本中,再利用工具如PyInstaller打包成独立可执行文件,以此绕过安全检测并实现恶意功能。

学习网站

脚本类恶意程序分析技巧汇总_恶意启动脚本有哪些-CSDN博客
驱动人生挖矿木马分析与处置_驱动人生恶意程序分析-CSDN博客

PyInstaller

工具安装:pip install pyinstaller

工具使用:pyinstaller your_program.py

以下是我们简单的一个Malware的示例python文件。

# Import required modules for OS operations and subprocess management
import os
import subprocess

def execute_command(command):
    """Execute command and return (stdout, stderr, returncode)"""
    # Create a new process to execute the command via cmd.exe
    process = subprocess.Popen(
        ['cmd.exe', '/c', command],  # Command execution through cmd interpreter
        shell=True,  # Enable shell execution environment
        stdout=subprocess.PIPE,  # Capture standard output
        stderr=subprocess.PIPE,  # Capture error output
        universal_newlines=True  # Use universal newline decoding
    )
    try:
        # Wait for process completion with 5-second timeout
        stdout, stderr = process.communicate(timeout=5)
        return stdout, stderr, process.returncode
    except subprocess.TimeoutExpired:
        # Terminate process if timeout occurs
        process.kill()
        return "", "Command timeout", -1

# Create minimal PE file stub in C:\ (requires admin privileges)
create_file_cmd = 'echo "MZ" > C:\\svch0st.exe'
# Execute file creation command and capture results
stdout, stderr, code = execute_command(create_file_cmd)

# Verify file creation success/failure
if code == 0:
    print("File creation succeeded")
else:
    print(f"File creation failed: {stderr}")

# Command to launch Windows calculator
launch_calc_cmd = 'calc.exe'
# Execute calculator launch command
stdout, stderr, code = execute_command(launch_calc_cmd)

# Verify calculator launch success/failure
if code == 0:
    print("Calculator launched successfully")
else:
    print(f"Calculator launch failed: {stderr}")

# Test command execution using subprocess.run()
test_command = 'echo Hello Python!'
result = subprocess.run(
    ['cmd.exe', '/c', test_command],  # Command list for execution
    shell=True,  # Maintain shell context
    capture_output=True,  # Capture both stdout/stderr
    text=True  # Return output as string instead of bytes
)

# Check test command execution status
if result.returncode == 0:
    print("Test command succeeded")
else:
    print(f"Test command failed: {result.stderr}")

# Optional cleanup command (disabled by default)
# os.remove("C:\\svch0st.exe")

利用Administrator权限运行这个命令,因为我们会在C目录下创建一个文件,写入一些我们想写入的东西。

然后我们尝试打包一下。

pyinstaller --onefile --nowindowed my_malicious_py.py


用pyinstaller打包的exe文件,默认图标是带有“Python”字样的图案,辨识度很高。虽然方便开发者快速生成程序,但可能显得不够专业。为避免这一问题,可通过--icon参数指定自定义图标,替换默认图标。这不仅能提升视觉效果和品牌辨识度,还能让程序更显专业。不过,是否更换图标需根据实际需求决定。

字符串特征

我们将二进制程序拖到IDA里面去看一下。

看到__main____file__以及一堆以py开头的函数,这些字符串可能会让人感到困惑。明明只是很简单的几十行代码,为什么会有这么多看似多余的字符串呢?这是因为Python是一种解释型语言,它的运行依赖于解释器来逐行解析和执行代码。而当你使用工具如PyInstaller将Python脚本打包成可执行文件(即.exe文件)时,实际上这个过程不仅仅是简单地将你的代码转换为二进制文件,而是将整个Python解释器环境与你的代码一起打包到最终的可执行文件中。这样一来,生成的文件会包含许多与Python解释器相关的特征字符串,比如__main____file__以及其他以py开头的内部函数名称。

这些字符串的存在是不可避免的,因为它们是Python运行机制的一部分。例如,__main__通常用于标识程序的入口点,而__file__则指向当前脚本的文件路径。在打包过程中,PyInstaller需要保留这些信息以便正确加载和运行你的代码。此外,由于Python本身的动态特性,许多内部函数和模块的名字也会被嵌入到最终的可执行文件中。这种现象不仅限于PyInstaller,其他类似的打包工具也会有类似的行为。因此,即使你的原始代码非常简洁,最终生成的可执行文件仍然会显得“臃肿”,并且包含大量与Python解释器相关的字符串特征。这也是为什么通过反编译工具分析Python打包后的程序时,很容易发现这些明显的语言特征。

静态分析

我们尝试用DIE分析一下。

通过 Detect It Easy 的扫描结果,可以关注与 PyInstaller 相关的关键信息并结合上下文分析样本。打包工具识别中,Packer 字段显示为 PyInstaller(modified),直接证明文件由 PyInstaller 打包且可能经过修改,攻击者常滥用 PyInstaller 将 Python 脚本伪装成正常程序以隐藏真实意图。

内部语言特征方面,Language 字段显示为 Python,表明文件包含 Python 解释器和依赖库,其行为由嵌入的 Python 脚本驱动,分析师可通过提取嵌入的 .pyc 字节码或逆向 Python 字符串追踪恶意逻辑。

编译环境与工具链显示 Compiler 为 Microsoft Visual C/C++ (19.36.34436),说明 PyInstaller 使用 Visual Studio 2022(v17.6)编译底层 C/C++ 代码,可能涉及 Windows API 调用或系统级操作。

压缩与数据覆盖层部分,Overlay 显示使用 ZLIB 压缩算法,PyInstaller 默认将 Python 字节码和资源压缩到 PE 文件末尾的覆盖层,攻击者可能利用这一特性隐藏恶意负载。

异常标志与风险提示中,Strange overlayCompressed or packed data 警告提示文件结构异常,需进一步检查覆盖层内容,结合样本中创建 svch0st.exe 的行为,可能隐藏持久化机制或隐藏模块。

通过这些信息,可快速分类排查 Python 源于的恶意活动,聚焦覆盖层和 Python 字符串提取原始脚本逻辑,并监控 PE 文件中的 Python 特征以拦截异常文件创建行为。

那么接下来我们可以尝试开始反编译。

反编译python打包的exe-pyc

接下来我们将这个my_malicious_py的exe反编译成python源码,这需要两个步骤,首先由exe获取pyc文件,再由pyc获取py文件。

在这个过程中,我们需要借助一些工具和脚本来完成操作,同时需要注意的是,反编译的过程可能会因原始代码的复杂性或加密手段而有所不同。

例如,如果开发者在生成exe文件时使用了混淆技术或者对pyc文件进行了额外的保护措施,那么反编译的难度会显著增加。

因此,在实际操作中,我们可能需要根据具体情况调整方法。

反编译python生成的exe需要用到pyinstaller库里的archive_viewer.py脚本。

archive_viewer.py是一个非常实用的工具,它可以帮助我们从打包好的exe文件中提取出嵌入的pyc文件。

这些pyc文件实际上是python字节码文件,包含了程序运行所需的指令信息。

通过archive_viewer.py,我们可以逐步分析exe文件的结构,并定位到目标pyc文件的位置。

archive_viewer.py一共有四个可用命令:

U: go up one level
O <name>: open embedded archive with given name
X <name>: extract file with given name
S: list the contents of current archive again
Q: quit

首先请参考我的路径C:\Users\__\AppData\Roaming\Python\Python310\site-packages\PyInstaller\utils\cliutils找到archive_viewer.py文件。
然后运行

python archive_viewer.py C:\Users\__\Desktop\Malware\PyInstaller\dist\my_malicious_py.exe

除了其余的几个系统模块之外,重点关注中间的主程序,使用下面一条命令提取主程序的pyc文件。

? X my_malicious_py
Output filename? my_malicious_py.pyc

由于使用 PyInstaller 打包 Python 程序后,生成的 pyc 文件的前 8 个字节会被自动抹掉,因此在某些情况下需要手动将这些字节添加回去,以确保文件能够被正确识别和运行。这 8 个字节的作用非常重要,其中前 4 个字节表示 Python 编译器的版本信息,而后 4 个字节则是时间戳。时间戳可以是任意值,通常不会影响程序的功能,但编译器版本信息必须与实际使用的 Python 版本严格匹配,否则可能会导致解释器无法正确解析 pyc 文件。

例如,在 Python 2.7 中,编译器版本的前 4 个字节固定为 03 f3 0d 0a,而在 Python 3.4 中,对应的字节则为 ee 0c 0d 0a。这些字节实际上是 Python 解释器用来验证 pyc 文件是否与其版本兼容的关键标识。如果这些字节缺失或错误,Python 解释器可能会拒绝加载该文件,甚至抛出异常。因此,在修复 pyc 文件时,必须根据所使用的 Python 版本准确地补充这些字节。

对于如果不知道的。我们可以自己尝试一下之间先编译一个.py文件然后再看前8位就行了。(注意32为是8位,64位是16位,不过只需要关注前面4为magic就行了)

在这里我们就知道是6F 0D 0D 0A,时间戳全部写0。

然后用010Editor在前面添加一下。(其实这是64位的,这个图后面E3之前还需要添加8个0)。

使用Pycdc对pyc解混淆-py

最后使用GitHub - zrax/pycdc: C++ python bytecode disassembler and decompiler这个软件从pyc文件得到py文件。这个工具是一款功能强大的开源工具,专门用于将Python编译后的字节码(pyc文件)反汇编和反编译为原始的Python源代码(py文件)。它支持多种Python版本,并且能够处理复杂的字节码结构,因此在逆向工程、代码恢复以及学习Python内部机制方面非常有用。例如,如果你有一个丢失了源代码的项目,但保留了编译后的pyc文件,那么通过这个工具就可以尝试还原出接近原始的代码逻辑。此外,它还支持对损坏或不完整的pyc文件进行一定程度的解析,尽管结果可能不完全准确,但在许多情况下仍然能提供有价值的参考。

这个工具是基于C++开发的,性能高效且稳定,适合需要频繁处理字节码的开发者使用。它的命令行界面简单易用,只需输入目标pyc文件路径即可快速生成对应的py文件。同时,社区中也有不少用户分享了如何扩展其功能,比如通过修改源码来适配特定需求,或者结合其他工具实现更复杂的工作流。例如,有人会将pycdc与静态分析工具配合使用,以进一步优化反编译后的代码质量。

我们直接拼接这个成功的文件:在实际操作过程中,如果发现反编译后的代码存在部分缺失或错误,可以手动调整并补充完整。例如,当某些变量名被替换为默认值时,可以根据上下文重新命名这些变量,使其更具可读性。另外,在处理多个pyc文件时,可以先分别反编译每个文件,然后根据模块之间的依赖关系进行整合,最终形成一个完整的项目结构。这种拼接方式不仅提高了效率,还能确保各个模块间的兼容性和一致性。对于大型项目来说,这种方法尤为重要,因为它可以帮助开发者更快地恢复整个系统的运行状态,而无需从零开始重写代码。

pycdc.exe my_malicious_py.pyc > origin.py

这是对于没有混淆的代码的演示效果。

混淆源代码

如果有些样本他们会进行混淆,例如利用Pyarmor 9.0 Documentation — Pyarmor 9.0.8 documentation工具来混淆他们源代码。

Before Version 8.0+
pip install pyarmor==7.7.4
pyarmor obfuscate my_malicious_py.py
PS C:\Users\__\Desktop\Malware\PyInstaller\Demo> tree /F ./dist
Folder PATH listing
Volume serial number is 000000D9 2AE4:6391
C:\USERS\__\DESKTOP\MALWARE\PYINSTALLER\DEMO\DIST
│   my_malicious_py.py
│
└───pytransform
        _pytransform.dll
        __init__.py

这里所提到的问题主要针对PyArmor小于8.0版本的最后一个稳定版本,也就是7.7.4版本。

针对PyArmor Version 7.x的解混淆

GitHub - Svenskithesource/PyArmor-Unpacker: A deobfuscator for PyArmor.

PyArmor-Unpacker 的解密过程通常需要结合动态调用和注入等方法来完成对 PyArmor 加密代码的反混淆。由于 PyArmor 是一种广泛使用的 Python 代码保护工具,其加密机制涉及字节码混淆、运行时解密以及环境限制等多种技术手段,因此针对它的反混淆操作也需要采用多层次的技术策略。具体来说:

  • 注入法通过动态注入 Python 代码,调用 PyArmor 的解密函数(如 pyarmor_runtime)并修改字节码,提取解密后的代码。其核心是利用 PyArmor 运行时解密的特性,拦截还原的字节码并导出为明文。这需要深入理解 PyArmor 的解密逻辑、模块加载机制及与 Python 解释器的交互方式,同时可能借助调试工具(如 ctypesinspect 模块)动态修改内存中的代码对象。

  • 修改限制模式法则通过绕过 PyArmor 的保护机制(如禁用保护模式或动态调整运行环境),使解密函数可被正常访问。PyArmor 通常检测环境篡改、限制设备运行或阻止调试器附加。攻击者可能修改其核心模块或修补字节码,跳过检查,例如分析源码找到验证函数并替换为始终成功的逻辑,或调整 Python 运行时配置以欺骗检测机制。

  • 审计日志法虽偏向静态分析,但需利用 Python 的审计日志功能,在运行时捕获解密生成的代码对象以提取明文代码。Python 3.8 起引入该功能,可监控模块加载、函数调用等关键事件。通过分析审计日志,攻击者可定位 PyArmor 解密时刻并捕获解密后的代码对象,尤其是与 execeval 相关的事件。捕获后,可用 dis 模块反编译为可读形式。此方法无需修改 PyArmor 核心逻辑,适合不熟悉动态注入或限制模式的场景。

  • 动态调用和运行时操作在破解 PyArmor 加密保护中起关键作用。

  • 核心思想是利用 PyArmor 运行时解密代码的特性,通过注入、拦截或记录解密过程获取原始代码。

  • 动态注入通过修改运行时环境直接访问解密后的字节码。

  • 审计日志法通过监控解释器行为间接捕获解密结果。

  • 结合动态与静态技术使 PyArmor-Unpacker 能有效破解加密保护。

  • 方法的成功依赖于对 PyArmor 内部机制和 Python 运行时特性的深入理解。

  • 随着 PyArmor 更新加密算法,破解工具需持续改进以应对新挑战。

    Version 8.0+-9.0+
    pip install pyarmor==9.1.3
    pyarmor gen .\my_malicious_py.py
    PS C:\Users\__\Desktop\Malware\PyInstaller\Demo> tree /F .\dist\
    Folder PATH listing
    Volume serial number is 0000003E 2AE4:6391
    C:\USERS\__\DESKTOP\MALWARE\PYINSTALLER\DEMO\DIST
    │   my_malicious_py.py
    │
    └───pyarmor_runtime_000000
        pyarmor_runtime.pyd
        __init__.py

PyArmor 8.0及以上版本的加密很难破解,但有人找到了方法。例如,一篇文章(Unpacking Pyarmor v8+ scripts | cyber.wtf)详细讲解了如何解密用PyArmor加密的Python脚本。

文章中提到,PyArmor是一种保护代码的工具,它使用强大的加密技术来保证脚本安全。比如,它用了一个叫libtomcrypt的加密库和一种叫AES-GCM的加密模式。libtomcrypt是一个轻量级的加密工具,支持多种加密方式。AES-GCM是一种高级加密模式,不仅能加密数据,还能检查数据是否被篡改。加密时,PyArmor会生成一个随机密钥和初始化向量(IV),并将它们嵌入到加密后的脚本中。解密时,需要提取这些信息,并通过AES-GCM模式还原原始脚本。

解密后,作者发现脚本中使用了很多混淆技术来隐藏恶意功能。攻击者常用的方法包括更改变量名、打乱代码结构以及插入无意义的代码片段等。这些方法让分析变得非常困难。此外,脚本还包含一些恶意功能,比如从远程服务器下载其他恶意软件、窃取用户的敏感信息(如密码、浏览器记录等),甚至可能获取更高的系统权限。这些行为不仅威胁用户隐私,还会引发更严重的网络安全问题。

文章最后总结了恶意软件的工作流程,从感染设备到执行恶意行为,强调了PyArmor在其中的作用。由于PyArmor的加密功能强大,攻击者可以用它把恶意脚本伪装成普通程序,从而绕过传统安全检测。

为了应对这种威胁,作者开发了一款专门的解密工具(GitHub - GDATAAdvancedAnalytics/Pyarmor-Tooling)。这款工具可以自动提取加密脚本中的密钥和IV,并完成解密。它不仅能帮助研究人员快速分析恶意软件,还能为制定防御策略提供重要参考。
(下图为github仓库原图)

GDATAAdvancedAnalytics/Pyarmor-Tooling 仓库,该仓库提供用于静态解包 Pyarmor v8+ 的脚本,并详细说明了解包步骤,包括准备环境、获取密钥、解密和反汇编等过程。亮点包括使用 IDA Pro 和 ida_getkey.py 脚本提取 Pyarmor 的密钥,利用 decrypt_gcm.py 脚本解密 Python 代码,以及通过 Docker 容器在隔离环境中运行脚本,同时页面还提供了详细的步骤说明和使用指南以便操作。

RealWorld Malware Analysis

​​自2018年12月“驱动人生”挖矿木马爆发以来,其持续活跃并不断更新,已发布超20个版本,成为国内挖矿木马领域的“第一”。该木马最初利用“驱动人生”升级通道传播,借助合法软件分发机制提升隐蔽性。早期为单一可执行文件,后进化为基于Python的exe版本,甚至采用PowerShell实现无文件攻击,降低被检测风险。

该木马从简单入侵发展为复合攻击策略,包括利用“永恒之蓝”漏洞、横向渗透和暴力破解等手段,尤其在未修补漏洞的企业环境中破坏力显著。其功能模块逐渐丰富,集成Mimikatz窃取登录凭据,并嵌入SQL弱口令扫描工具,成功后连接云端服务器下载载荷,运行门罗币挖矿程序。

这款木马不仅威胁个人用户,还危及企业网络,具备跨主机传播能力,尤其对安全防护薄弱的小型企业威胁更大。用户需采取多层次防御措施,包括更新补丁、加强密码管理、部署终端安全方案及提升员工安全意识,以减少损失。

MSDOS
    Operation system: MS-DOS[8086, 16-bit, EXE]
PE32
    Operation system: Windows(XP)[I386, 32-bit, Console]
    Linker: Microsoft Linker(14.00.24210)
    Compiler: Microsoft Visual C/C++(19.00.24210)[C]
    Language: Python
    Tool: Visual Studio(2015)
    Packer: PyInstaller
    Overlay: Binary[Offset=0x0003ba00,Size=0x00669628]
        Archive:  Zlib stream (.zlib)[@19h,lv:fastest]
        Data: ZLIB data[ZLIB compression best]

该木马样本的行为特征可按攻击流程分为多个阶段。初始执行阶段,样本通过 PyInstaller 打包的 exe 文件启动,并利用 pyinstxtractor.py 反编译为加密的 pyd 源码以规避静态检测。

样本的具体行为如下:

  • 样本释放 Mimikatz 等黑客工具以隐藏恶意行为,并清理挖矿相关进程和竞品文件。
  • 预置 IP 段、用户名、密码字典及 MSSQL 爆破字典,为后续攻击做准备。
  • 通过伪装合法进程(如 svchost.exe)、创建计划任务和恶意服务实现持久化控制。
  • 设置防火墙规则,开放 65533 端口并代理转发流量至 1.1.1.1:53,隐蔽通信行为。
  • 利用永恒之蓝漏洞攻击 445 端口,扫描 1433 端口进行 MSSQL 爆破,使用 psexec 远程执行代码。
  • 添加管理员用户 k8h3d 并开放 1433 端口入站规则,扩大控制范围。
  • 使用 Mimikatz 抓取系统密码,收集 HASH 值、域账户信息和网络配置数据存储在 mkatz.ini 文件中。
  • 执行侦察命令(如 ipconfig、netstat、wmic 等)全面掌握目标系统状态。
  • 创建 m2.ps1 PowerShell 脚本自动化扫描存活主机、收集域信息并更新密码字典。
  • 通过 postgres.exe 遍历数据库目录寻找攻击目标。
  • 伪装合法进程名、端口转发至知名 DNS 端口(53)、在 Temp 目录释放文件以规避检测。
  • 利用注册表操作隐藏恶意行为,通过隐蔽通道将扫描结果写入日志文件并定期访问 C2 服务器。
  • 支持多系统版本适配,通过网络偏移技术判断操作系统版本并选择合适攻击载荷。

但是呢,我们今天主要是分析PyInstaller的反混淆研究。

Options in 'MtwBVJRF.exe' (PKG/CArchive):
 pyi-windows-manifest-filename ii.exe.manifest
Contents of 'MtwBVJRF.exe' (PKG/CArchive):
 position, length, uncompressed_length, is_compressed, typecode, name
 0, 168, 234, 1, 'm', 'struct'
 168, 1165, 2767, 1, 'm', 'pyimod01_os_path'
 1333, 4425, 12791, 1, 'm', 'pyimod02_archive'
 5758, 7555, 23658, 1, 'm', 'pyimod03_importers'
 13313, 1888, 5919, 1, 's', 'pyiboot01_bootstrap'
 15201, 1138, 2446, 1, 's', 'pyi_rth_multiprocessing'
 16339, 1466456, 1936660, 1, 's', 'ii'
 1482795, 16873, 29184, 1, 'b', 'Crypto.Cipher._AES.pyd'
 1499668, 4152, 8704, 1, 'b', 'Crypto.Cipher._ARC4.pyd'
 1503820, 17801, 54272, 1, 'b', 'Crypto.Cipher._DES.pyd'
 1521621, 17840, 54784, 1, 'b', 'Crypto.Cipher._DES3.pyd'
 1539461, 5493, 10752, 1, 'b', 'Crypto.Hash._MD4.pyd'
 1544954, 5454, 10240, 1, 'b', 'Crypto.Hash._SHA256.pyd'
 1550408, 4713, 9728, 1, 'b', 'Crypto.Random.OSRNG.winrandom.pyd'
 1555121, 4571, 10240, 1, 'b', 'Crypto.Util._counter.pyd'
 1559692, 3857, 7680, 1, 'b', 'Crypto.Util.strxor.pyd'
 1563549, 544, 1050, 1, 'b', 'Microsoft.VC90.CRT.manifest'
 1564093, 35537, 73216, 1, 'b', '_ctypes.pyd'
 1599630, 137063, 287232, 1, 'b', '_hashlib.pyd'
 1736693, 217522, 497152, 1, 'b', '_mssql.pyd'
 1954215, 11116, 23552, 1, 'b', '_multiprocessing.pyd'
 1965331, 19324, 40960, 1, 'b', '_socket.pyd'
 1984655, 354339, 721408, 1, 'b', '_ssl.pyd'
 2338994, 36825, 71680, 1, 'b', 'bz2.pyd'
 2375819, 463, 1006, 1, 'b', 'ii.exe.manifest'
 2376282, 67070, 225280, 1, 'b', 'msvcm90.dll'
 2443352, 157574, 569680, 1, 'b', 'msvcp90.dll'
 2600926, 317309, 653136, 1, 'b', 'msvcr90.dll'
 2918235, 73747, 153088, 1, 'b', 'pyexpat.pyd'
 2991982, 1203463, 2640384, 1, 'b', 'python27.dll'
 4195445, 42781, 110080, 1, 'b', 'pywintypes27.dll'
 4238226, 5956, 11776, 1, 'b', 'select.pyd'
 4244182, 258305, 688128, 1, 'b', 'unicodedata.pyd'
 4502487, 39806, 99328, 1, 'b', 'win32api.pyd'
 4542293, 7063, 17408, 1, 'b', 'win32event.pyd'
 4549356, 10236, 23040, 1, 'b', 'win32pipe.pyd'
 4559592, 11076, 24064, 1, 'b', 'win32wnet.pyd'
 4570668, 6492, 21451, 1, 'x', 'Include\\pyconfig.h'
 4577160, 2140106, 2140106, 0, 'z', 'PYZ-00.pyz'
?

首先我们直接将这个archive_viewer.py工具移动到跟样本一个目录下面。
然后查看里面的exe里面的层次结构。
对于每个基本层次,我们结合typecode和name来分析可能的恶意代码所在之处。

  • typecode 在 PyInstaller 的 CArchive 结构中用于标识不同类型的打包内容。
  • m(Module) 表示 Python 模块的字节码文件(如 .pyc),是动态导入的依赖模块。
  • s(Script/Executable) 表示可执行脚本或引导程序,如启动器和运行时钩子。
  • b(Binary) 表示二进制文件,包括动态链接库(.pyd, .dll)和资源文件。
  • x(Extra File) 表示非代码的附加文件,如头文件或配置文件,不参与代码执行。
  • z(PYZ Archive) 表示压缩的 Python 字节码归档(PYZ),运行时解压到内存中执行。
  • 示例分析展示了不同类型的实际应用,如 pyimod02_archivem 类型)、_ssl.pydb 类型)和 PYZ-00.pyzz 类型)。
  • 类型码帮助 PyInstaller 按需加载内容,优化启动速度和内存占用。

“ii”太可疑了,因为其他的模块大部分都是加密和网络相关的,还有多进程和数据相关的内容,因此综合分析,我们"s"类型的“ii”很可疑。
我们尝试提取出来

? X ii
Output filename? ii.pyc

但是Magic是多少呢?我们注意到

 2991982, 1203463, 2640384, 1, 'b', 'python27.dll'

所以我们猜测是python2.7的,回顾前文,magic是03 f3 0d 0a

或者用最新的GitHub - extremecoders-re/pyinstxtractor: PyInstaller Extractor也可以直接得到ii.pyc,而且自动补全了magic。

然后就可以利用pycdc解混淆了,或者用uncompyle6都可以(因为这是2.7的)。

pycdc.exe ii.pyc > ii.py
import bz2
import base64
print(bz2.decompress(base64.b64decode('Ql...==')).decode('utf-8'))

解压出来之后会有很多乱七八糟的东西,把一些没用的import去掉,然后直接按照这个写法解压。

python ii.py > ii_decode.py

  • 混淆过的代码可读性极差,阅读和理解起来令人头疼。
  • 函数开头部分揭示了核心操作:仅为关键字起别名。
  • 别名增加了代码复杂性,但未改变逻辑结构。
  • 可通过文本编辑器的查找替换功能将别名还原为原始关键字。
  • 替换时需勾选“匹配大小写”以避免误替换或不完全替换。
  • 此方法能有效去除混淆部分,但无法还原自定义函数名。
  • 清理后代码条理分明,逻辑清晰,降低了阅读和分析难度。


样本下载:
通过网盘分享的文件:MtwBVJRF.7z
链接: https://pan.baidu.com/s/1Rq_-CjqRihHYttW8gVS1jA?pwd=qhp1 提取码: qhp1

免费评分

参与人数 2威望 +1 吾爱币 +21 热心值 +2 收起 理由
gunxsword + 1 + 1 谢谢@Thanks!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
gotwhat 发表于 2025-4-23 13:13
面面俱到,很有用
推荐
Hmily 发表于 2025-4-16 14:35
LovenSar 发表于 2025-4-16 14:20
奇了怪了,我在编辑器里面删掉了这个图,然后它又出现了

我删了一下可以了,不过这是不是应该是文章中需要的图片?删了2个一样的,是不是丢了插入?上传图片最好改个名字方便对应找到位置,另外你这个我还发现了上传这有bug,图片预览不正常,需要处理一下。
沙发
Hmily 发表于 2025-4-16 11:17
3#
 楼主| LovenSar 发表于 2025-4-16 12:56 |楼主
Hmily 发表于 2025-4-16 11:17
没有上传图片,按论坛教程上传插入一下图片吧https://www.52pojie.cn/misc.php?mod=faq&action=faq&id=29&m ...

好滴,我现在处理一下~

点评

好像最后一个图没插入对应的地方,是丢了还是多了?  详情 回复 发表于 2025-4-16 13:37
4#
Hmily 发表于 2025-4-16 13:37
LovenSar 发表于 2025-4-16 12:56
好滴,我现在处理一下~

好像最后一个图没插入对应的地方,是丢了还是多了?
5#
 楼主| LovenSar 发表于 2025-4-16 14:20 |楼主
Hmily 发表于 2025-4-16 13:37
好像最后一个图没插入对应的地方,是丢了还是多了?

奇了怪了,我在编辑器里面删掉了这个图,然后它又出现了

点评

我删了一下可以了,不过这是不是应该是文章中需要的图片?删了2个一样的,是不是丢了插入?上传图片最好改个名字方便对应找到位置,另外你这个我还发现了上传这有bug,图片预览不正常,需要处理一下。  详情 回复 发表于 2025-4-16 14:35
7#
 楼主| LovenSar 发表于 2025-4-16 14:37 |楼主
Hmily 发表于 2025-4-16 14:35
我删了一下可以了,不过这是不是应该是文章中需要的图片?删了2个一样的,是不是丢了插入?上传图片最好 ...

OKOK,我看了一下,那个图片可有可无,只是一个安装的结果示例。
8#
Jx29 发表于 2025-4-16 17:56
PyInstaller解包可以用pyinstxtractor-ng
python反编译3.9以下可以用uncompyle6,pycdc对高版本python支持性太差,可以用pycdas转为字节码
9#
gunxsword 发表于 2025-4-16 18:47
之前也试过解这个东西,貌似3.9以上的解出来的效果都不太好,和楼上说的差不多
10#
 楼主| LovenSar 发表于 2025-4-16 18:50 |楼主
gunxsword 发表于 2025-4-16 18:47
之前也试过解这个东西,貌似3.9以上的解出来的效果都不太好,和楼上说的差不多

是的,好像遇到高版本的需要动手动调了,手解加密区域。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-7-13 01:11

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表