PatchRequest/DLLProxyFramework
GitHub: PatchRequest/DLLProxyFramework
这是一个自动化生成DLL代理项目的框架,用于DLL旁加载和劫持研究,以实现代码注入和隐蔽执行。
Stars: 11 | Forks: 0
# DLL 代理框架
## 为何使用 DLL 旁加载?
DLL 旁加载允许您的代码——无论是游戏作弊器、C2 代理还是红队植入物——在一个合法的、已签名的进程中执行。对于正在处理警报或查看日志的防御者来说,正在运行的 `.exe` 文件看起来完全无害:它是一个带有有效签名的可信供应商二进制文件。您的负载只是作为它本来就会加载的 DLL 一同运行。
本框架自动化了繁琐的部分:分析目标 DLL 的导出函数,生成将所有函数调用转发到原始函数的代理代码,并为您的负载提供一个干净的插槽。选择一个[可劫持的 DLL](https://hijacklibs.net),运行一个命令,放入您的代码,构建即可。
生成用于 DLL 旁加载和劫持研究的代理 DLL 项目。将其指向一个 DLL,获得一个准备编译的项目,该项目会镜像所有导出函数并将其转发到原始 DLL——同时为您的负载代码预留一个插槽。
## 工作流程
1. 选择一个目标 DLL(例如来自 [hijacklibs.net](https://hijacklibs.net))
2. 运行生成器
3. 使用您的加载器代码编辑 `payload.c`
4. 使用 MSVC 或 MinGW 构建
5. 部署
```
python generate.py C:\Windows\System32\version.dll --payload --embed --block
```
## 功能特性
- **导出函数镜像** — 分析 PE 导出表并生成汇编跳板(`jmp [ptr]`),透明地将所有调用转发到原始 DLL。处理命名导出、仅序号导出、转发导出以及 C++ 名称修饰。
- **嵌入模式** (`--embed`) — 将原始 DLL 作为 PE 资源嵌入。加载时,它会提取到 `%TEMP%` 并加载。无需分发第二个 DLL 文件。
- **负载线程** (`--payload`) — 生成一个 `payload.c` 模板。您的代码在所有导出函数解析后,在一个单独的线程中运行。
- **阻塞模式** (`--block`) — 挂起主线程,以便进程在您的负载完成之前不会退出。使用两层方法:主挂起 + atexit 回退。无加载锁问题。
- **双编译器支持** — 生成 MSVC(`.asm` + `build_msvc.bat`)和 MinGW(`.S` + `Makefile`)构建文件。
- **双架构支持** — x86 和 x64,根据输入 DLL 自动检测。
## 安装
```
pip install -r requirements.txt
```
需要 Python 3.10+ 和 Visual Studio (MSVC) 或 MinGW-w64 进行构建。
## 使用方法
```
python generate.py [options]
Options:
-o, --output DIR Output directory (default: ./output/_proxy/)
--embed Embed original DLL as a PE resource
--payload Include payload thread template
--block Block process exit until payload finishes (implies --payload)
--compiler {msvc,gcc,both} Target compiler (default: both)
--arch {x86,x64,auto} Target architecture (default: auto-detect)
--original-name NAME Runtime filename for original DLL (non-embed mode)
-v, --verbose Show all exports and generated files
--dry-run Show what would be generated without writing
```
### 示例
最小代理(无负载,从磁盘加载原始 DLL):
```
python generate.py C:\Windows\System32\version.dll
```
完整的旁加载设置,包含嵌入式 DLL 和阻塞负载:
```
python generate.py C:\Windows\System32\version.dll --payload --embed --block
```
仅 MSVC,详细输出:
```
python generate.py C:\Windows\System32\dbghelp.dll --payload --compiler msvc -v
```
## 生成的项目结构
```
version_proxy/
├── proxy.c # DllMain, function pointer table, init/cleanup
├── proxy.h # Exported function pointer declarations
├── exports.def # Module definition file (maps exports to trampolines)
├── trampolines.asm # MSVC MASM — one jmp [ptr] per export
├── trampolines.S # MinGW GAS — same, AT&T/Intel syntax
├── payload.c # Your code goes here
├── payload.h # Payload thread declaration
├── resource.rc # Embedded DLL resource (--embed)
├── resource.h # Resource IDs
├── original_version.dll # Copy of original DLL (--embed)
├── build_msvc.bat # Build with cl.exe + ml64.exe
└── Makefile # Build with gcc + as
```
## 构建
**MSVC** — 打开开发者命令提示符:
```
cd output\version_proxy
build_msvc.bat
```
**MinGW**:
```
cd output\version_proxy
mingw32-make
```
## 工作原理
### 导出函数转发
每个导出函数都变成一个汇编跳板,通过函数指针进行跳转:
```
; x64 MASM
proxy_GetFileVersionInfoA PROC
jmp QWORD PTR [fp_GetFileVersionInfoA]
proxy_GetFileVersionInfoA ENDP
```
`.def` 文件将原始导出名称映射到跳板标签:
```
GetFileVersionInfoA = proxy_GetFileVersionInfoA @1
```
在 `DLL_PROCESS_ATTACH` 时,加载原始 DLL 并通过 `GetProcAddress` 解析所有函数指针。调用透明地流经——无寄存器损坏,无调用约定问题。
### 阻塞模式
当宿主进程会立即退出时(例如打印 `--help`),`--block` 会保持进程存活:
1. **主要机制**:负载线程在加载器锁释放后挂起主线程。主线程在到达 `main()` 或 `ExitProcess` 之前被冻结。负载运行,然后调用 `ExitProcess(0)`。
2. **回退机制**:如果主线程赢得了竞态条件,`atexit` 处理程序会阻塞,直到负载发出完成信号。
两条路径均无死锁——不涉及加载器锁。
## 测试
测试套件验证了针对 `version.dll` 的所有模式组合,适用于两种编译器。需要开发者命令提示符(MSVC)。如果 PATH 中有 `gcc` 和 `mingw32-make`,GCC 测试会自动运行。
```
cd test
run_tests.bat
```
| 测试 | 编译器 | 模式 | 验证内容 |
|------|--------|------|----------|
| 1 | MSVC | `--embed --payload` | 嵌入式 DLL 提取 + 导出函数转发 |
| 2 | MSVC | `--embed --payload --block` | 阻塞模式保持进程存活,负载完成 |
| 3 | MSVC | `--payload` | 并排 DLL 加载 + 导出函数转发 |
| 4 | MSVC | `--payload --block` | 无嵌入的阻塞模式 |
| 5 | GCC | `--embed --payload` | GCC 嵌入式 DLL 提取 + 转发 |
| 6 | GCC | `--embed --payload --block` | GCC 带嵌入的阻塞模式 |
| 7 | GCC | `--payload` | GCC 并排加载 + 转发 |
| 8 | GCC | `--payload --block` | GCC 无嵌入的阻塞模式 |
预期输出:
```
============================================================
DLL Proxy Framework - Test Suite
============================================================
[*] Compiling test host...
[+] test_host.exe ready
[*] MinGW detected - GCC tests enabled
[TEST 1/MSVC] --embed --payload
------------------------------------------------------------
[+] PASS: MSVC embed forwarding works
[TEST 2/MSVC] --embed --payload --block
------------------------------------------------------------
[+] PASS: MSVC embed + block works
[TEST 3/MSVC] --payload (no embed, no block)
------------------------------------------------------------
[+] PASS: MSVC non-embed forwarding works
[TEST 4/MSVC] --payload --block (no embed)
------------------------------------------------------------
[+] PASS: MSVC non-embed + block works
[TEST 5/GCC] --embed --payload
------------------------------------------------------------
[+] PASS: GCC embed forwarding works
[TEST 6/GCC] --embed --payload --block
------------------------------------------------------------
[+] PASS: GCC embed + block works
[TEST 7/GCC] --payload (no embed, no block)
------------------------------------------------------------
[+] PASS: GCC non-embed forwarding works
[TEST 8/GCC] --payload --block (no embed)
------------------------------------------------------------
[+] PASS: GCC non-embed + block works
============================================================
Results: 8 passed, 0 failed
============================================================
```
## 示例:链接 Rust 作弊器/植入物
如果您已经有一个用 Rust 编写的项目(作弊器、代理、植入物等),您可以将其静态链接到代理 DLL 中。结果是一个单独的 `.dll` 文件——您的 Rust 代码在被劫持的进程中运行,无需将额外文件落盘。
### 1. 将您的 Rust 项目编译为静态库
在您 Rust 项目的 `Cargo.toml` 中,将 crate 类型设置为 `staticlib`:
```
[lib]
crate-type = ["staticlib"]
```
通过 C 链接暴露一个入口点:
```
// src/lib.rs
use std::fs;
use std::io::Write;
#[unsafe(no_mangle)]
pub extern "C" fn cheat_main() {
// your cheat / implant / agent logic here
// this runs in its own thread inside the hijacked process
let pid = std::process::id();
let msg = format!("Cheat running in PID {}\n", pid);
if let Ok(mut f) = fs::File::create("proof.txt") {
let _ = f.write_all(msg.as_bytes());
}
}
```
构建它:
```
cargo build --release
```
这将生成 `target\release\your_crate.lib`。
### 2. 生成代理项目
```
python generate.py C:\Windows\System32\version.dll --payload --embed --block
```
### 3. 编辑 `payload.c` 以调用您的 Rust 代码
用以下内容替换生成的 `payload.c`:
```
#include "payload.h"
extern void cheat_main(void);
DWORD WINAPI payload_main(LPVOID lpParam) {
(void)lpParam;
cheat_main();
return 0;
}
```
### 4. 将 Rust `.lib` 链接到构建中
**MSVC** — 编辑 `build_msvc.bat`,将 `.lib` 及其依赖项添加到链接行:
```
cl /nologo /LD ^
proxy.c payload.c trampolines.obj resource.res ^
/link /DEF:exports.def /OUT:version.dll ^
C:\path\to\your_crate.lib ^
kernel32.lib user32.lib ws2_32.lib advapi32.lib userenv.lib ^
ntdll.lib bcrypt.lib msvcrt.lib
```
**MinGW** — 编辑 `Makefile`:
```
RUSTLIB = /path/to/your_crate.lib
$(TARGET): $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $^ $(DEF) $(RUSTLIB) -lkernel32 -luser32 -lws2_32 -ladvapi32 -luserenv -lbcrypt -lntdll
```
### 5. 构建和部署
```
build_msvc.bat
```
输出文件 `version.dll` 是一个包含以下内容的单个文件:
- 代理导出表(将所有调用转发到嵌入的原始 DLL)
- 嵌入的原始 `version.dll`(运行时提取)
- 您的整个 Rust 作弊器,已静态链接
### 部署布局
```
target_app/
├── legit_signed_app.exe # Trusted binary that loads version.dll
└── version.dll # Your proxy (contains original + your Rust code)
```
就这样。一个文件。日志中的 `.exe` 是一个已签名的供应商二进制文件。
## 非嵌入模式
```
target_app/
├── version.dll # Your proxy
├── original_version.dll # The real DLL (renamed)
└── app.exe # Host application
```
## 许可证
MIT
标签:DLL hijacking, DLL sideloading, DLL注入, Gophish, Hakrawler, pdftotext, 代理DLL, 可视化界面, 安全意识培训, 安全测试, 导出镜像, 恶意代码加载, 恶意软件研究, 攻击性安全, 有效载荷执行, 汇编生成, 流量审计, 私有化部署, 网络可见性, 网络安全, 自动回退, 进程嵌入, 进程隐藏, 逆向工具, 防御规避, 隐私保护, 风险发现