vk-candpython/peldr

GitHub: vk-candpython/peldr

peldr 是一款军事级的 Windows PE 打包器与反射加载器,用于实现无文件加密执行。

Stars: 1 | Forks: 1

# 👾 peldr
[![Platform](https://img.shields.io/badge/platform-Windows-blue?logo=windows&logoColor=white)](https://www.microsoft.com/en-us/windows) [![Language](https://img.shields.io/badge/language-C%2FC%2B%2B-00599C?logo=c%2B%2B)](https://en.cppreference.com/) [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE) *高级 PE 打包与反射加载 — 压缩、加密、无文件执行*
## 📖 目录 - [English](#english) - [📋 概述](#-overview) - [✨ 功能](#-features) - [🔒 完整打包流水线](#-complete-packing-pipeline) - [🚀 快速开始](#-quick-start) - [⚙️ 构建时配置标志](#️-build-time-configuration-flags) - [⚙️ 深度技术分析](#️-deep-technical-analysis) - [📁 输出](#-output) - [⚠️ 要求](#️-requirements) - [🔧 故障排除](#-troubleshooting) - [Русский](#русский) - [📋 概述](#-обзор) - [✨ 功能](#-возможности) - [🔒 完整打包流水线](#-полный-конвейер-упаковки) - [🚀 快速开始](#-быстрый-старт) - [⚙️ 构建时配置标志](#️-флаги-конфигурации-времени-сборки) - [⚙️ 深度技术分析](#️-глубокий-технический-анализ) - [📁 输出](#-результат) - [⚠️ 要求](#️-требования) - [🔧 故障排除](#-устранение-неполадок) # 英文 ## 📋 概述 **PELDR** — 是一个军事级 PE 打包器和反射加载器,可将标准的 Windows 可执行文件 (EXE/DLL) 转换为自包含、加密、无文件执行的二进制文件。 它结合了自定义的 RLE 压缩、流式 XOR 密码以及一个完全反射的加载器存根,该存根通过哈希解析 API,规避调试,并且从不将原始映像写入磁盘。 ### 独特之处? | 组件 | 实现 | |---|---| | **反射加载器** | 纯 C,无标准库,所有功能通过 ntdll 哈希查找解析 | | **API 哈希** | 类 DJB 哈希,带随机密钥;所有函数名均已隐藏 | | **RLE 压缩** | 自定义字节级游程编码 — 通常减少 20-50% 体积 | | **XOR 流密码** | 可变密钥长度(16-128 字节)+ 反馈 — 每个字节依赖于所有之前的字节 | | **ETW 绕过** | 运行时在内存中修补 `EtwEventWrite` | | **反调试** | 检查 `BeingDebugged` 标志、`ProcessDebugPort`、`ProcessDebugFlags`,隐藏线程 | | **伪装为 ntdll** | 可选地用 ntdll.dll 的头覆盖原始映像头 | | **无文件执行** | 载荷直接解密并解压到 `MEM_TOP_DOWN` 分配中,受保护并执行 | | **动态代码策略** | 映射后设置 `ProcessDynamicCodePolicy` 以防止进一步的代码注入 | | **加载器自清理** | 所有内部函数指针在使用后清零 | ## ✨ 功能 ### 核心打包 | 功能 | 描述 | |---|---| | 🗜️ **RLE 压缩** | 字节级 RLE,带 `0x80` 重复标志,最小游程长度 3 | | 🔐 **XOR 流密码** | 密钥长度 16-128 字节,非线性反馈,与盐相关 | | 🔍 **API 哈希** | 每个导入的函数通过预计算的类 DJB 哈希解析 — 无明文名称 | | 🧠 **反射加载** | 将载荷映射到内存,处理重定位、导入、TLS 并执行 | ### 编译与链接 | 功能 | 描述 | |---|---| | 🏗️ **最小化 C 环境** | `-nostdlib -nostartfiles -ffreestanding` — 无 CRT,无标准库 | | 🧹 **极致精简** | `--strip-all --discard-all --gc-sections` + 自定义节区清除 | | 🛡️ **编译器加固** | 禁用栈保护器,无异常表,无 PLT,隐藏可见性 | | 📦 **静态 PIE** | 位置无关可执行文件 — 可从任意基址运行 | ### 运行时保护 | 功能 | 描述 | |---|---| | 🚫 **反调试** | `BeingDebugged` 标志、`ProcessDebugPort` 检查、`ProcessDebugFlags` 和线程隐藏 | | 🛡️ **ETW 修补** | 内存中覆写 `EtwEventWrite` 为 `xor eax,eax; ret` | | 🔒 **动态代码策略** | 加载后启用 `ProcessDynamicCodePolicy` 以防止执行新代码 | | 🧹 **指针清零** | 所有敏感函数指针在使用后清空 | | 🧥 **ntdll 伪装** | 可选 — 用 ntdll.dll 的头替换宿主映像头 | ## 🔒 完整打包流水线 ``` PHASE 1: PE VALIDATION ├── Checks DOS signature (MZ) ├── Validates NT signature (PE) └── Confirms x86‑64 architecture PHASE 2: RLE COMPRESSION ├── Flag byte: 0x00‑0x7F = literal run, 0x80‑0xFF = repeat run ├── Minimum repeat threshold: 3 identical bytes ├── Maximum literal run: 126 bytes └── Exact pre‑allocation for output buffer PHASE 3: XOR STREAM ENCRYPTION ├── Random key length 16‑128 bytes ├── Stream cipher with non‑linear feedback and salt └── Each byte depends on all previous bytes PHASE 4: STUB ASSEMBLY ├── Pre‑compiled loader stub appended ├── Embedded key, compressed + encrypted payload ├── Total length written at the end for overlay reading └── Optional GUI subsystem flag PHASE 5: RUNTIME (Loader Execution) ├── Reads overlay from own file via NtQueryInformationProcess + NtReadFile ├── Decrypts and decompresses payload in memory ├── Allocates image with MEM_TOP_DOWN and PAGE_GUARD ├── Maps sections, performs relocations and imports ├── Handles TLS callbacks ├── Optionally disguises as ntdll └── Jumps to entry point (or DllMain for DLL) ``` ## 🚀 快速开始 ### 📥 下载 您可以从 [Releases](https://github.com/vk-candpython/peldr/releases/tag/v1.0.0) 页面下载预构建的发布二进制文件。 或者克隆并从源代码构建: ``` git clone https://github.com/vk-candpython/peldr.git cd peldr ``` ### 📦 构建 ``` # 构建加载器(stub) gcc -m64 -nostdlib -nodefaultlibs -nostartfiles -static-pie -e Main -Os \ -Wl,-O2,--nxcompat,--dynamicbase,-x,--sort-common,--exclude-all-symbols,\ --no-insert-timestamp,--no-seh,--build-id=none,--strip-all,--discard-all,--gc-sections \ -s -fvisibility=hidden -fno-semantic-interposition -fomit-frame-pointer \ -ffreestanding -fmerge-constants -ffunction-sections -fdata-sections \ -fno-builtin -fno-common -fno-plt -fno-exceptions -fno-stack-check \ -fno-stack-protector -fno-stack-clash-protection -fno-ident \ -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-math-errno \ -fno-trapping-math -o loader.exe loader.c # 构建打包器 g++ -m64 -static-pie -mconsole -municode -O3 \ -Wl,-O2,--nxcompat,-x,--sort-common,--exclude-all-symbols,\ --no-insert-timestamp,--no-seh,--build-id=none,--strip-all,--discard-all,--gc-sections \ -s -fvisibility=hidden -fno-semantic-interposition -fomit-frame-pointer \ -fmerge-constants -ffunction-sections -fdata-sections -fno-common -fno-plt \ -fno-exceptions -fno-ident -fno-unwind-tables -fno-asynchronous-unwind-tables \ -fno-math-errno -fno-trapping-math -o peldr.exe peldr.cpp ``` ### 🏃 使用 ``` # 打包可执行文件(默认为控制台子系统) peldr.exe myapp.exe # 使用 GUI 子系统打包 peldr.exe -w myapp.exe # 打包多个文件 peldr.exe app1.exe app2.dll ``` **输出:** ``` [ OK ]: Starting packing of (1) file mode(CONSOLE) [ INFO ]: Start processing -> C:\Users\...\myapp.exe [ OK ]: compressed: (142144 -> 89123) bytes | saved: 53021 bytes (37%) [ OK ]: outfile(./peldr-myapp.exe, 123456 bytes) [ INFO ]: time ................. (0.007s) [ INFO ]: End processing -> C:\Users\...\myapp.exe [ OK ]: Successfully packed of (1) ``` ## ⚙️ 构建时配置标志 加载器 (`loader.c`) 暴露了几个编译时 `#define` 开关来控制其行为。它们在源文件顶部设置: ``` #define USING_ANTIDEBUG TRUE #define USING_DISGUISE_AS_NTDLL FALSE #define USING_ERASE_PE_SIGNATURE FALSE #define USING_DYNAMIC_CODE_POLICY FALSE #define USING_SIGNATURE_DLL_POLICY FALSE ``` ### 标志描述 | 标志 | 默认值 | 描述 | |---|---|---| | **`USING_ANTIDEBUG`** | `TRUE` | 启用所有反调试措施:`BeingDebugged` 检查、`ProcessDebugPort`、`ProcessDebugFlags`、线程隐藏和 ETW 修补。仅当打包的二进制文件必须被调试时才禁用。 | | **`USING_DISGUISE_AS_NTDLL`** | `FALSE` | 当为 `TRUE` 时,加载器用真实的 `ntdll.dll` 的头覆盖宿主映像的 PE 头。这使得该进程在内存转储和工具(如 Process Hacker)中看起来像 `ntdll.dll`。 | | **`USING_ERASE_PE_SIGNATURE`** | `FALSE` | 当为 `TRUE` 时,加载后将映射映像的 `MZ` 和 `PE` 签名清零,移除经典的 DOS/NT 魔术字节。 | | **`USING_DYNAMIC_CODE_POLICY`** | `FALSE` | 当为 `TRUE` 时,调用 `NtSetInformationProcess` 设置 `ProcessDynamicCodePolicy` 以在载荷加载后禁止动态代码生成(防止进一步的 VirtualAlloc + RWX)。 | | **`USING_SIGNATURE_DLL_POLICY`** | `FALSE` | 当为 `TRUE` 时,设置 `ProcessSignaturePolicy` 将 DLL 加载限制为仅 Microsoft 签名的二进制文件。 | **注意:** 更改这些标志需要重新构建加载器存根并将其重新嵌入打包器。 ## ⚙️ 深度技术分析 ### 反射加载器 (loader.c) 加载器作为宿主进程运行。它: - 通过 `NtQueryInformationProcess` → `ProcessImageFileName` 查询自身映像路径来读取附加的覆盖数据 - 打开并读取文件尾部以获取打包的数据 - 使用嵌入的密钥解密并解压缩载荷 - 使用 `MEM_TOP_DOWN` + `PAGE_GUARD` 分配新的内存区域以实现反调试 - 映射头、节区,处理基址重定位和导入 - 处理异常目录 (`RtlAddFunctionTable`) 和加载配置(安全 cookie) - 可选地擦除 PE 签名并将原始映像头伪装为 ntdll - 调用 TLS 回调,最后调用入口点(或 DllMain) ### API 哈希 所有函数都使用预计算的哈希从 `ntdll.dll` 解析。哈希函数是一个带有随机密钥 (`KEY_HASH_STR`) 的类 DJB 算法。在构建过程中,`hash.py` 为所需函数生成 `#define` 列表。运行时,加载器遍历 ntdll 的导出表,对每个名称进行哈希,并与嵌入的哈希进行比较。这防止了静态分析看到导入的函数名。 ### 压缩 (RLE) 自定义字节导向的游程编码: - 字面量游程:长度 1-126,后跟原始字节 - 重复游程:长度 3-127,由 0x80 标记,后跟重复的字节 - 针对 PE 文件中常见的零填充和重复模式进行了优化 ### 加密 (XOR 流密码) 具有内部状态和非线性反馈的流密码。 每次构建的密钥长度随机变化(16、32、64 或 128 字节)。 ### 反调试与规避 - 检查 `PEB->BeingDebugged` - 使用 `ProcessDebugPort` 和 `ProcessDebugFlags` 调用 `NtQueryInformationProcess` - 通过 `NtSetInformationThread(ThreadHideFromDebugger)` 向调试器隐藏当前线程 - 通过临时使其内存可写,将 `EtwEventWrite` 修补为 `xor eax, eax; ret` - 可选地设置 `ProcessDynamicCodePolicy` 和 `ProcessSignaturePolicy` ### 构建器 (peldr.cpp) 用 C++ 编写,进行了大量优化: - 使用 `ifstream` 模拟内存映射 I/O - 单遍压缩和原地加密 - 随机密钥生成,由 `std::random_device` 提供种子 - 预编译的加载器存根 (`STUB_EXE[]`) 作为静态字节数组嵌入,并在构建时进行定制(例如 GUI 子系统标志) ## 📁 输出 ``` original.exe → peldr-original.exe ``` **输出二进制文件属性:** - 包含完整的加载器存根 + 加密的载荷 - 剥离了所有符号,节区头已清零 - 无需将原始 PE 写入磁盘即可反射执行 - 通常比原始文件**小 20-50%** ## ⚠️ 要求 | 要求 | 版本 | 备注 | |---|---|---| | **构建器操作系统** | Windows | 在 Windows 上构建和测试 | | **目标操作系统** | Windows 7+ | 加载器使用自 NT 6.1 起可用的 NT API 函数 | | **架构** | x86_64 | 加载器和打包映像都必须是 64 位 | | **编译器(加载器)** | GCC (MinGW‑w64) | `-nostdlib` 构建 | | **编译器(构建器)** | G++ (MinGW‑w64) | C++17 filesystem | ## 🔧 故障排除 | 问题 | 解决方案 | |---|---| | `打包的二进制文件崩溃` | 原始 PE 可能需要特定的 DLL 或 COM 初始化。尝试先打包一个简单的 EXE。 | | `编译失败` | 使用准确提供的标志;确保您的 MinGW‑w64 支持 `-static-pie`。 | | `防病毒软件标记 peldr.exe` | 打包器可能被检测为“packer”或“hacktool”。这是预期的;请在隔离环境中使用。 | | `文件访问错误` | 确保您在输出目录中拥有读/写权限。 | | `载荷解密失败` | 不要单独修改加载器存根;从同一个 commit 构建两者。 | # 俄语 ## 📋 概述 **PELDR** — 这是一个军事级的 PE 打包器,具有反射加载功能。它将标准的 Windows 可执行文件(EXE/DLL)转换为自主的、加密的、无文件执行的二进制文件。 使用自定义的 RLE 压缩、流式 XOR 密码和完全反射的加载器,该加载器通过哈希解析 API,绕过调试,并且从不将原始映像保存到磁盘。 ### 独特之处? | 组件 | 实现 | |---|---| | **反射加载器** | 纯 C,无标准库,所有功能通过 ntdll 中的哈希查找 | | **API 哈希** | 带随机密钥的类 DJB 哈希;函数名已隐藏 | | **RLE 压缩** | 自定义字节级编码 — 通常压缩 20-50% | | **流式 XOR 密码** | 可变密钥长度(16-128 字节)+ 反馈 | | **绕过 ETW** | 在内存中将 `EtwEventWrite` 修补为 `xor eax,eax; ret` | | **反调试** | 检查 `BeingDebugged`、`ProcessDebugPort`、`ProcessDebugFlags`,隐藏线程 | | **伪装为 ntdll** | 可选地用 ntdll.dll 的头覆盖原始映像头 | | **无文件执行** | 解密和解压缩直接发生在分配的内存中,不写入磁盘 | ## ✨ 功能 ### 打包 | 功能 | 描述 | |---|---| | 🗜️ **RLE 压缩** | 字节级 RLE,带 0x80 标志,最小序列 3 字节 | | 🔐 **流式 XOR 密码** | 密钥 16-128 字节,非线性反馈 | | 🔍 **API 哈希** | 所有函数通过预先计算的哈希查找 — 名称不可见 | | 🧠 **反射加载** | 将映像加载到内存,处理重定位、导入、TLS 并启动 | ### 编译与链接 | 功能 | 描述 | |---|---| | 🏗️ **最小化 C 环境** | `-nostdlib -nostartfiles -ffreestanding` — 无 CRT | | 🧹 **极致精简** | `--strip-all --discard-all --gc-sections` | | 🛡️ **编译器保护** | 无栈保护器,无异常表,无 PLT,隐藏可见性 | | 📦 **静态 PIE** | 位置无关代码 — 可从任何基址运行 | ### 运行时保护 | 功能 | 描述 | |---|---| | 🚫 **反调试** | 检查 PEB 和 DebugPort 标志,隐藏线程 | | 🛡️ **ETW 修补** | 在内存中覆写 `EtwEventWrite` | | 🔒 **动态代码策略** | 加载后禁止执行新代码 | | 🧹 **指针清零** | 所有敏感的函数指针在使用后被清除 | | 🧥 **伪装为 ntdll** | 可选用 ntdll.dll 的头替换映像头 | ## 🔒 完整打包流水线 *(详细图表请参见英文版)* ## 🚀 快速开始 ### 📥 下载 您可以从 [Releases](https://github.com/vk-candpython/peldr/releases/tag/v1.0.0) 页面下载预构建的二进制文件。 或者克隆存储库并从源代码构建: ``` git clone https://github.com/vk-candpython/peldr.git cd peldr # 构建加载器(stub) gcc -m64 -nostdlib ... -o loader.exe loader.c # 构建打包器 g++ -m64 -static-pie ... -o peldr.exe peldr.cpp # 打包文件 peldr.exe myapp.exe ./peldr-myapp.exe ``` ## ⚙️ 构建时配置标志 加载器 (`loader.c`) 包含几个控制其行为的 `#define` 标志: ``` #define USING_ANTIDEBUG TRUE #define USING_DISGUISE_AS_NTDLL FALSE #define USING_ERASE_PE_SIGNATURE FALSE #define USING_DYNAMIC_CODE_POLICY FALSE #define USING_SIGNATURE_DLL_POLICY FALSE ``` ### 标志描述 | 标志 | 默认值 | 描述 | |---|---|---| | **`USING_ANTIDEBUG`** | `TRUE` | 启用所有反调试措施:`BeingDebugged` 检查、`ProcessDebugPort`、`ProcessDebugFlags`、线程隐藏和 ETW 修补。仅当需要调试打包的文件时才禁用。 | | **`USING_DISGUISE_AS_NTDLL`** | `FALSE` | 当为 `TRUE` 时,用真实的 `ntdll.dll` 的头替换主映像的 PE 头,从而在内存中伪装进程。 | | **`USING_ERASE_PE_SIGNATURE`** | `FALSE` | 当为 `TRUE` 时,加载后擦除映射映像的 `MZ` 和 `PE` 签名。 | | **`USING_DYNAMIC_CODE_POLICY`** | `FALSE` | 当为 `TRUE` 时,调用 `ProcessDynamicCodePolicy`,禁止载荷加载后进一步创建可执行内存。 | | **`USING_SIGNATURE_DLL_POLICY`** | `FALSE` | 当为 `TRUE` 时,设置 `ProcessSignaturePolicy`,仅允许加载由 Microsoft 签名的 DLL。 | **注意:** 更改标志需要重新构建加载器存根并将其重新插入打包器。 ## ⚙️ 深度技术分析 *(细节与英文版相同)* ## 📁 输出 ``` оригинал.exe → peldr-оригинал.exe ``` ## ⚠️ 要求 | 要求 | 版本 | 备注 | |---|---|---| | **构建器操作系统** | Windows | 在 Windows 上构建和测试 | | **目标操作系统** | Windows 7+ | NT API 自 NT 6.1 起可用 | | **架构** | x86_64 | 仅 64 位 | | **编译器(加载器)** | GCC (MinGW‑w64) | | | **编译器(构建器)** | G++ (MinGW‑w64) | C++17 | ## 🔧 故障排除 | 问题 | 解决方案 | |---|---| | `打包的二进制文件崩溃` | 原始文件可能需要某些 DLL 或 COM 初始化。尝试使用简单的 EXE。 | | `编译错误` | 使用精确指定的标志;确保您的 MinGW‑w64 支持 `-static-pie`。 | | `防病毒软件报警` | 对于打包器来说这是预期的行为;请在隔离环境中使用。 | | `文件读取错误` | 检查输出目录中的访问权限。 | | `解密失败` | 不要单独修改加载器;从同一个 commit 构建两个组件。 |
**[⬆ 返回顶部](#-peldr)** *Windows 的 PE 打包与反射加载*
标签:Awesome列表, C++开发, PE加载器, Raspberry Pi, Windows二进制打包, 云资产清单, 代码生成, 内存执行, 军用级安全, 加密载荷, 压缩载荷, 反射式加载, 客户端加密, 恶意软件技术, 攻击路径可视化, 无文件执行, 渗透测试工具, 端点可见性, 逆向工程, 隐蔽执行, 零磁盘足迹, 高性能加载, 黑客工具