vk-candpython/peldr
GitHub: vk-candpython/peldr
peldr 是一款军事级的 Windows PE 打包器与反射加载器,用于实现无文件加密执行。
Stars: 1 | Forks: 1
# 👾 peldr
[](https://www.microsoft.com/en-us/windows)
[](https://en.cppreference.com/)
[](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二进制打包, 云资产清单, 代码生成, 内存执行, 军用级安全, 加密载荷, 压缩载荷, 反射式加载, 客户端加密, 恶意软件技术, 攻击路径可视化, 无文件执行, 渗透测试工具, 端点可见性, 逆向工程, 隐蔽执行, 零磁盘足迹, 高性能加载, 黑客工具