aziz-haddadi/packdetect

GitHub: aziz-haddadi/packdetect

一款Python实现的PE文件加壳检测与自动脱壳命令行工具,通过熵分析、签名扫描和启发式算法识别已知及未知加壳器。

Stars: 0 | Forks: 0

# PackDetect 一款用于 Windows PE 二进制文件(`.exe`、`.dll`、`.sys`)的命令行加壳检测与脱壳工具。专为逆向工程师和恶意软件分析师打造。 ``` ____ _ ____ _ _ | _ \ __ _ ___| | _| _ \ ___| |_ ___ ___| |_ | |_) / _` |/ __| |/ / | | |/ _ \ __/ _ \/ __| __| | __/ (_| | (__| <| |_| | __/ || __/ (__| |_ |_| \__,_|\___|_|\_\____/ \___|\__\___|\___|\__| ``` ## 功能特性 - **Shannon 熵分析** —— 针对每个节区和整个文件的熵分析,带有彩色输出 - **签名数据库** —— 支持 UPX, MPRESS, ASPack, PECompact, Themida/WinLicense, VMProtect, FSG, Petite, NSIS - **未知加壳检测** —— 结构化启发式算法,无需已知签名即可捕获自定义/混淆加壳器 - **自动脱壳** —— 通过 subprocess 调用 `upx -d` 或 `mpress -decompress` 以支持已知的加壳器 - **批处理模式** —— 扫描整个目录并获取摘要表 - **JSON 导出** —— 机器可读输出,便于集成到管道中 - **Rich UI + 纯文本回退** —— 使用 `rich` 库输出漂亮的彩色内容;在 `--plain` 模式下优雅降级为纯 ASCII - **零 PE 库依赖** —— PE 解析器使用纯标准库 `struct` 实现;仅有 `rich` 是可选依赖 ## 工作原理 检测运行在三个层级,每一层都计入加权置信度评分: ``` ┌─────────────────┐ ┌──────────────────┐ ┌──────────────────────┐ │ Layer 1 │ │ Layer 2 │ │ Layer 3 │ │ Entropy │──▶│ Signature scan │──▶│ Heuristics │ │ Shannon H(x) │ │ magic bytes + │ │ EP location, import │ │ per section │ │ section names │ │ count, size ratios │ └─────────────────┘ └──────────────────┘ └──────────────────────┘ │ Verdict + confidence% ``` **第 1 层 —— 熵 (Entropy):** Shannon 熵(0–8 位/字节)。加壳/加密节区的得分通常在 7.0 以上。正常编译的代码位于 4.5–6.5 之间。 **第 2 层 —— 签名:** 搜索特定加壳器的魔数(例如 `UPX!`)和已知节区名称(例如 `.MPRESS1`)。贡献高达 95% 的基础置信度。 **第 3 层 —— 启发式特征(未知加壳检测):** 即使在签名不匹配时也能触发的结构异常: - 仅存在于虚拟内存的节区 (raw_size ≈ 0, virtual_size >> 0) —— 加壳器解压缩的占位符 - 入口点位于 `.text` 之外 - 无导入表 —— 加壳二进制文件会动态重建其 IAT - 所有节区的原始/虚拟大小比率偏低 - 非标准节区名称 ## 安装说明 ``` # Clone git clone https://github.com/you/packdetect cd packdetect # 创建并激活 virtual environment python -m venv .venv .venv\Scripts\activate # Windows source .venv/bin/activate # Mac / Linux # 安装(editable mode —— 代码更改立即生效) pip install -e . # 或不使用 Rich(仅 plain ASCII mode) pip install -e . --no-deps ``` **环境要求:** - Python 3.12+ - `rich >= 13.0`(可选 —— 安装后可获得彩色输出) - `upx` 位于 PATH 中(可选 —— 自动脱壳 UPX 二进制文件所需) - `mpress` 位于 PATH 中(可选 —— 自动脱壳 MPRESS 二进制文件所需) ## 快速入门 —— 使用内置的真实恶意软件样本进行测试 本仓库在 `malware-lab/` 目录下包含一个 **真实的 UPX 加壳恶意软件样本**,以便您可以立即使用真实的加壳二进制文件测试该工具。 ### Rich 输出的完整扫描 ``` packdetect scan ..\..\malware-lab\7d7655e9446fd41dc1ae859435f39c250964532bc604c9bf6d737992430d645e.exe ``` ### 纯 ASCII 输出(无颜色) ``` packdetect scan ..\..\malware-lab\7d7655e9446fd41dc1ae859435f39c250964532bc604c9bf6d737992430d645e.exe --plain ``` ### 保存 JSON 报告 ``` packdetect scan ..\..\malware-lab\7d7655e9446fd41dc1ae859435f39c250964532bc604c9bf6d737992430d645e.exe --save-json ``` 这将在样本旁边生成一份 `.packdetect.json` 报告,包含完整的分析内容 —— 各节区熵、签名匹配、启发式发现以及判定结果。 ### 尝试自动脱壳 请先确保已安装 `upx` 并位于您的 PATH 中([在此下载](https://upx.github.io)),然后运行: ``` packdetect unpack ..\..\malware-lab\7d7655e9446fd41dc1ae859435f39c250964532bc604c9bf6d737992430d645e.exe ``` 这会在后台调用 `upx -d`,并在原始文件旁生成一个 `_unpacked.exe`。重新扫描解包后的文件以确认熵已回落到正常范围(约 5.x): ``` packdetect scan ..\..\malware-lab\7d7655e9446fd41dc1ae859435f39c250964532bc604c9bf6d737992430d645e_unpacked.exe ``` ### 预期输出 ``` ╭──────────────────────── Verdict ─────────────────────────╮ │ ⚠ PACKED │ │ │ │ Confidence : ██████████ 97% │ │ Risk level : HIGH │ │ Packer : UPX │ ╰────────────────────────────────────────────────────────────╯ Section Entropy Bar Flag ───────── ───────── ───────────────────────── ────────── UPX0 0.0000 ░░░░░░░░░░░░░░░░░░░░░░░░ NORMAL UPX1 7.88xx ████████████████████████ HIGH .rsrc 3.4xxx ██████████░░░░░░░░░░░░░░ NORMAL [HIT] UPX — magic bytes "UPX!" found in stub header ``` ## 使用方法 ### 扫描单个二进制文件 ``` packdetect scan malware.exe ``` 输出包括: - 文件信息(大小、MD5、SHA-256、架构、入口点) - 带有置信度评分和风险等级的判定面板 - 带有彩色条形图的各节区熵表 - 签名扫描结果(命中 / 未检测到) - 带有独立评分的启发式发现 - 如果检测到支持的加壳器,会显示脱壳提示 ### 纯 ASCII 输出(无 Rich) ``` packdetect scan malware.exe --plain ``` ### JSON 输出(适合管道传输) ``` packdetect scan malware.exe --json packdetect scan malware.exe --json | jq .verdict ``` ### 将 JSON 报告保存在文件旁 ``` packdetect scan malware.exe --save-json # 写入 malware.packdetect.json ``` ### 自动脱壳 ``` packdetect unpack upx_packed.exe # 调用:upx -d upx_packed.exe -o upx_packed_unpacked.exe ``` ### 批量扫描目录 ``` packdetect batch ./samples/ packdetect batch ./samples/ --all # include non-PE extensions packdetect batch ./samples/ --json # JSON array to stdout packdetect batch ./samples/ --save-json # saves packdetect_batch.json ``` ## 运行测试套件 本项目包含 **26 个单元测试**,覆盖了整个引擎 —— 熵计算、PE 解析、签名检测、启发式逻辑、判定计算以及端到端分析。 它们仅使用通过 `struct` 构建的 **合成内存 PE 二进制文件** —— 不需要真实的恶意软件。 ### 安装 pytest 并运行 ``` pip install pytest pytest tests/ -v ``` ### 预期输出 ``` tests/test_engine.py::TestShannonEntropy::test_all_zeros PASSED tests/test_engine.py::TestShannonEntropy::test_all_same_byte PASSED tests/test_engine.py::TestShannonEntropy::test_two_equal_bytes PASSED tests/test_engine.py::TestShannonEntropy::test_uniform_distribution PASSED tests/test_engine.py::TestShannonEntropy::test_random_like_data PASSED tests/test_engine.py::TestShannonEntropy::test_empty PASSED tests/test_engine.py::TestPEParser::test_parses_minimal_pe PASSED tests/test_engine.py::TestPEParser::test_rejects_non_pe PASSED tests/test_engine.py::TestPEParser::test_rejects_too_short PASSED tests/test_engine.py::TestPEParser::test_upx_section_names PASSED tests/test_engine.py::TestSignatureScanner::test_upx_magic_detected PASSED tests/test_engine.py::TestSignatureScanner::test_upx_section_name_detected PASSED tests/test_engine.py::TestSignatureScanner::test_mpress_section_name_detected PASSED tests/test_engine.py::TestSignatureScanner::test_clean_binary_no_matches PASSED tests/test_engine.py::TestSignatureScanner::test_confidence_is_positive PASSED tests/test_engine.py::TestHeuristics::test_clean_no_heuristics PASSED tests/test_engine.py::TestHeuristics::test_high_entropy_flagged PASSED tests/test_engine.py::TestHeuristics::test_virtual_only_section_flagged PASSED tests/test_engine.py::TestHeuristics::test_high_entropy_exec_section_flagged PASSED tests/test_engine.py::TestVerdictComputation::test_signature_hit_gives_packed PASSED tests/test_engine.py::TestVerdictComputation::test_no_sig_high_heuristic_gives_unknown PASSED tests/test_engine.py::TestVerdictComputation::test_clean_binary_verdict PASSED tests/test_engine.py::TestVerdictComputation::test_suspicious_medium_score PASSED tests/test_engine.py::TestAnalyseIntegration::test_clean_binary PASSED tests/test_engine.py::TestAnalyseIntegration::test_upx_magic_in_file PASSED tests/test_engine.py::TestAnalyseIntegration::test_result_fields_populated PASSED 26 passed in 0.22s ``` ### 运行覆盖率报告 ``` pip install pytest-cov pytest tests/ -v --cov=packdetect --cov-report=term-missing ``` ### 各测试类覆盖的内容 | 类名 | 测试内容 | |-------|--------------| | `TestShannonEntropy` | 熵计算边缘情况 —— 全零、均匀分布、随机数据 | | `TestPEParser` | PE 头解析 —— 有效的 PE32、ELF 拒绝、节区名称解码 | | `TestSignatureScanner` | UPX 魔数、MPRESS 节区名称、干净文件返回空列表 | | `TestHeuristics` | 仅虚拟内存节区、高熵可执行节区、干净二进制文件基线 | | `TestVerdictComputation` | 已知签名 → 已加壳、仅启发式 → 未知加壳器、干净基线 | | `TestAnalyseIntegration` | 对合成 PE 二进制文件的完整 `analyse()` 管道端到端测试 | ## 退出码 | 代码 | 含义 | |------|---------| | 0 | 干净 / 成功 | | 2 | 检测到加壳二进制文件 | | 3 | 可疑(非结论性) | | 4 | 不支持脱壳 | | 5 | 尝试脱壳但失败 | 在脚本中使用退出码: ``` packdetect scan "$file" --plain if [ $? -eq 2 ]; then echo "Packed! Attempting unpack..." packdetect unpack "$file" fi ``` ## JSON 输出格式 ``` { "file": { "path": "malware.exe", "size": 45056, "md5": "...", "sha256": "...", "arch": "x86", "is_pe": true, "entry_point": "0x00001000", "entry_point_section": "UPX1", "elapsed_seconds": 0.012 }, "entropy": { "overall": 7.621, "sections": [ { "name": "UPX0", "entropy": 0.12, "raw_size": 0, "virtual_size": 65536, "flag": "NORMAL" }, { "name": "UPX1", "entropy": 7.89, "raw_size": 40960, "virtual_size": 40960, "flag": "HIGH" } ] }, "signatures": [ { "name": "UPX", "version": "3.x", "offset": "0x00000050", "confidence": 95, "description": "..." } ], "heuristics": [ { "name": "Virtual-only section", "description": "...", "score": 30 } ], "verdict": { "verdict": "packed", "packer": "UPX", "confidence": 97, "risk": "HIGH", "unpack_supported": true, "unpack_command": "upx -d malware.exe -o malware_unpacked.exe" } } ``` ## 项目结构 ``` packdetect/ ├── packdetect/ │ ├── __init__.py version string │ ├── __main__.py CLI — argparse, commands: scan / unpack / batch │ ├── engine.py analysis engine — PE parser, entropy, signatures, heuristics │ └── output.py display — Rich renderer, plain renderer, JSON serialiser ├── malware-lab/ │ └── 7d7655e9...exe real UPX-packed malware sample for testing ├── tests/ │ ├── __init__.py │ └── test_engine.py 26 unit tests (no real binaries needed) ├── .gitignore ├── LICENSE ├── pyproject.toml ├── requirements.txt └── README.md ``` ## 扩展签名数据库 打开 `packdetect/engine.py` 并在 `SIGNATURE_DB` 中添加条目: ``` { "name": "MyPacker", "version": "1.0", "magic": [b"\xDE\xAD\xBE\xEF"], # bytes to search anywhere in file "section_names": [".mypkr"], # section name substrings "ep_stub": bytes([0x60, 0xE8, 0x00]), # bytes at start of first exec section "description": "MyPacker v1.0 signature", "confidence": 85, "unpack_cmd": None, # or "mytool -d {input} -o {output}" }, ``` ## 涵盖的概念(作品集要点) | 概念 | 位置 | |---------|-------| | PE 格式 (DOS/COFF/Optional headers, sections) | `engine.py` → `PEParser` | | Shannon 熵 | `engine.py` → `shannon_entropy()` | | 加壳器签名 / YARA 风格匹配 | `engine.py` → `SIGNATURE_DB`, `scan_signatures()` | | 未知加壳器启发式特征 | `engine.py` → `run_heuristics()` | | Subprocess 编排 | `engine.py` → `attempt_unpack()` | | 使用 argparse 进行 CLI 设计 | `__main__.py` | | Rich 终端 UI 及纯文本回退 | `output.py` | | 结构化 JSON 报告 | `output.py` → `to_json()` | | 用于脚本集成的退出码 | `__main__.py` | | 无外部二进制文件的单元测试 | `tests/test_engine.py` | ## 免责声明 本工具及内置样本仅用于**教育和合法的安全研究目的**。 `malware-lab/` 中的恶意软件样本获取自 [MalwareBazaar](https://bazaar.abuse.ch) —— 一个由 abuse.ch 为安全研究社区维护的公开存储库。 请勿在隔离环境之外执行该样本。作者不对滥用行为承担责任。
标签:Conpot, DAST, DeepSeek, PE文件分析, Python安全工具, UPX, VMProtect, Windows安全, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 加壳检测, 可执行文件, 启发式扫描, 恶意软件分析, 无依赖PE解析, 无服务器架构, 熵值分析, 特征码检测, 端点检测与响应, 脱壳工具, 逆向工程, 静态分析