diabloidyobane/PEReconstruct

GitHub: diabloidyobane/PEReconstruct

恢复运行时被擦除 PE 头的手动映射 DLL,伪造合成头使其能被 IDA 正常静态分析。

Stars: 0 | Forks: 0

# PEReconstruct 恢复并静态分析在运行时被擦除 PE 头的**手动映射 DLL**。适用于任何你可以调用 `OpenProcess()` 的进程。无需驱动程序、调试器或符号。纯 stdlib Python 3 实现。 常见目标:恶意软件加载器、进程内植入物、加壳程序、反作弊模块,以及任何由自定义用户模式加载器而非 Windows 加载器映射的代码。 ## 何时需要此工具 手动映射的 DLL 通常会: 1. 由自定义的用户模式加载器加载(而不是 Windows 加载器) 2. 在 `DllMain` 之后擦除其 `MZ` / `PE\0\0` 头,这样常规的内存扫描就不会发现它们 3. 有时也会擦除节表,只留下原始的 RX 页面 普通的转储工具(`scylla`、`pe-sieve`)在头信息丢失时,要么难以发现它们,要么根本无法找到。PEReconstruct 通过运行时特征(可执行 + 私有)找到这些内存区域,并伪造一个合成的 PE 头,以便 IDA 能够像分析普通 DLL 一样分析这些转储。 ## 流水线 ``` ┌─────────────────────────────────┐ │ Target process (running) │ │ PID = whatever │ └────────────┬────────────────────┘ │ ┌────────────────────────┼────────────────────────┐ ▼ ▼ ▼ ┌──────────────────┐ ┌──────────────────────┐ ┌────────────────────┐ │ scan_exec_ │ │ scan_pe_deep.py │ │ dump_manualmap.py │ │ private.py │ │ │ │ │ │ │ │ Aggressive PE-sig │ │ Looks for MZ at │ │ Lists every RX │ │ sweep — finds wiped │ │ region start (the │ │ MEM_PRIVATE │ │ DLLs by their PE\0\0 │ │ "well-behaved" │ │ region. The big │ │ at +e_lfanew. │ │ case where headers │ │ one (~1-10 MB, │ │ Catches anti-dumping │ │ survive). │ │ entropy ~7) is │ │ tricks where MZ is │ │ │ │ usually it. │ │ zeroed but PE isn't. │ │ │ └────────┬─────────┘ └──────────┬───────────┘ └─────────┬──────────┘ │ │ │ └───────────────────────┼────────────────────────┘ │ (you pick the right region from the surveys) ▼ ┌────────────────────────────────┐ │ raw .bin file on disk │ │ "execpriv__ │ │ 0x.bin" │ │ filename encodes runtime VA │ │ you'll feed to step 3. │ └────────────┬───────────────────┘ │ ▼ ┌────────────────────────────────┐ │ rebuild_headerless.py │ │ │ │ Forges a synthetic PE header │ │ in the first 0x1000 bytes: │ │ - DOS stub │ │ - PE32+ NT headers │ │ - Single .text section RX │ │ covering the whole image. │ └────────────┬───────────────────┘ │ ▼ ┌────────────────────────────────┐ │ _reconstructed.dll │ │ (loadable PE — open in IDA) │ └────────────┬───────────────────┘ │ ▼ ┌────────────────────────────────┐ │ analyze_hooks.py │ │ resolve_exports.py │ │ │ │ Reconstruct the IAT from │ │ absolute addresses found in │ │ the dump; name every API │ │ call by module+offset. │ └────────────────────────────────┘ ``` ## 快速开始 ``` # 1. 找到你的目标进程 tasklist | findstr /i "" # 记下 PID # 2. 调查可执行私有区域(无头捕获器) py 01_acquire/scan_exec_private.py --pid --dump # 2b. 可选地也可尝试深度 PE-sig 扫描 py 01_acquire/scan_pe_deep.py --pid # 2c. 如果目标具有有效的 MZ 头(对于隐藏模块很罕见),这是最快的方法 py 01_acquire/dump_manualmap.py --pid # 输出:位于 C:\path\to\execprivate_\ 的 .bin 文件夹 # 通过大小 (1-10 MB) 和熵值 (~6-7) 识别候选项。 # 文件名模式: execpriv__0x.bin # 3. 重构 PE — 从文件名传入运行时基址 py 02_reconstruct/rebuild_headerless.py \ execprivate_/execpriv__.bin \ 0x \ target_reconstructed.dll # 4. 在 IDA 中打开 target_reconstructed.dll。自动分析。完成。 # 5. 可选:用导入 + 命名的 API 调用进行丰富 py 03_enrich/analyze_hooks.py --pid \ --target target_reconstructed.dll \ --target-base 0x \ --out target_imports.md ``` ## 目录布局 | 文件夹 | 脚本 | 用途 | |---|---|---| | `01_acquire/` | `scan_exec_private.py` | **主要工具。** 列出所有 RX MEM_PRIVATE 区域。优先使用此工具——适用于无头的转储。 | | `01_acquire/` | `scan_pe_deep.py` | 跨所有已提交内存的激进 PE 签名扫描。能捕获 `MZ` 被清零但 `PE\0\0` 未被清零的转储。 | | `01_acquire/` | `dump_manualmap.py` | 严格的 `MZ` 位于区域起始处的检测器。仅在目标保留头信息时使用。 | | `01_acquire/` | `dump_contiguous_image.py` | 将目标中的连续 VA 范围拼接成单个转储,对未映射的间隙进行零填充。 | | `02_reconstruct/` | `rebuild_headerless.py` | **核心工具。** 在原始转储的前 0x1000 字节上伪造 DOS+NT+节表。 | | `03_enrich/` | `analyze_hooks.py` | 遍历跳板页,通过绝对地址模式识别被 Hook 的函数。生成 markdown 报告。 | | `03_enrich/` | `resolve_exports.py` | 将 `module.dll:0xOFFSET` 解析为 `kernel32!CreateFileA+0x12` 这样的名称。 | ## 重建注意事项 **无节恢复。** `rebuild_headerless.py` 会声明一个覆盖整个映像 RX 的 `.text` 节。原始文件可能包含独立的 `.rdata` / `.data` / `.pdata` 节——它们将变得与代码无法区分。副作用: - IDA 会尝试将数据区域作为代码反汇编(看起来像乱码) - 高熵的嵌入数据(加密块、压缩资产)会显示为一段“无效指令”——这没关系,只要不尝试将它们作为函数解释即可 - `.idata` 导入表已消失——除非重建导入(使用 `analyze_hooks.py`),否则无法按名称跟踪 API 调用 **无重定位表。** 重建的 DLL 硬编码了原始的运行时 `ImageBase`。如果你尝试通过 `LoadLibrary` 实际加载它,ASLR 会对其重定位,从而导致转储内部的绝对指针失效。**只能将输出用于 IDA 中的静态分析**,不能用于重新注入。 **被擦除的填充。** 如果加载器将转储内部的区域(PE 头填充、已释放的分配)清零,这些字节将永久丢失。重建无法恢复它们——IDB 中过去存在数据的地方将出现零填充的间隙。 **加固的进程。** 当目标安装了内核回调(例如 `ObRegisterCallbacks`)时,`OpenProcess(PROCESS_VM_READ)` 会被阻止。你将收到 `ERROR_ACCESS_DENIED (5)` 或一个被剥离权限的句柄。要继续操作: - 在启动前暂停保护服务(仅适用于作为独立用户模式服务运行的保护) - 或者使用内核模式的读取原语——通过 `kdmapper` 使用你自己的驱动程序,或任何基于 `\Device\PhysicalMemory` 的辅助工具。这里的转储脚本都假设使用用户模式 RPM,否则会静默失败。 ## Python 要求 仅使用标准库。在 Windows 上通过 CPython 3.12 测试。无需 pip 安装。 ## 结合 Claude Code 使用 PEReconstruct 专为通过编码代理驱动而设计——每个脚本都基于 `argparse`,打印结构化输出,并写入确定性的文件名。一个典型的 Claude Code 会话如下所示: 有用的提示词: - *"调查 PID `` 中隐藏的模块,并告诉我哪些区域看起来像手动映射的 DLL。"* - *"在基址 `0x` 处重建 ``,并通过 IDA-Pro MCP 服务器在 IDA 中打开它。"* - *"对重建的 DLL 运行 `analyze_hooks.py`,并总结它从哪些 Win32 模块导入。"* 提示:这与 [ida-pro-mcp](https://github.com/mrexodia/ida-pro-mcp) 配合使用效果很好。 重建后,将 Claude 指向 IDA MCP 服务器,以通过 MCP 驱动反汇编、反编译和符号命名。 ## 安装为 Claude Code 技能 此仓库中的 `skills/pe-reconstruct/` 目录是一个可直接使用的 [Claude Code skill](https://docs.claude.com/en/docs/claude-code/skills)。 安装后,当你询问有关转储、恢复或分析手动映射/无头 DLL 的问题时,Claude Code 会自动调用它。 ``` # 为当前用户安装(所有项目) mkdir -p ~/.claude/skills cp -r skills/pe-reconstruct ~/.claude/skills/ # 或者仅为一个项目安装 mkdir -p .claude/skills cp -r skills/pe-reconstruct .claude/skills/ ``` 该技能的 `SKILL.md` 会准确地告诉 Claude 针对哪个任务运行哪个脚本以及如何将它们串联起来。 ## 许可证 MIT — 请参阅 [LICENSE](LICENSE)。
标签:API接口, Claude Code, DAST, IDA Pro分析, OpenProcess, PE头抹除恢复, PE重建, SecList, Windows内存扫描, 云安全监控, 云资产清单, 免杀分析, 内存取证, 加载器分析, 反作弊对抗, 安全对抗, 安全工具开发, 恶意软件分析, 手动映射DLL, 数字取证, 无驱动无调试器, 端点可见性, 纯标准库Python, 自动化脚本, 进程内存读取, 逆向工程, 静态分析