Frunner is a lightweight, single-header C++17 library designed for in-memory reflective execution of Windows x64 PE executables and managed .NET assemblies directly from RAM (raw bytes or Base64) without touching the disk.
- Header-Only: Drop
frunner.hinto your project and callFrunner::ExecuteBase64(...). - Multi-Runtime Support: Native support for C/C++, Rust, Go, and C# (.NET Framework).
- Command-Line & PEB Patching: Real-time patching of
GetCommandLineWand PEB structures for passing CLI arguments directly to loaded runtimes. - SEH & Exception Tables: Automatic registration of structured exception tables (
RtlAddFunctionTable) required by modern runtimes (Rust / Go). - TLS Directory Handling: Proper initialization of Thread Local Storage callbacks and slots.
- CLR Hosting: In-process hosting of .NET Framework via
ICLRMetaHost/AppDomain. - Verbose Diagnostic Engine: Toggleable detailed logging for debugging execution stages.
| Language / Runtime | Architecture | Status | Notes |
|---|---|---|---|
| C / C++ (MSVC / GCC / Clang) | x64 | Beta | Full base relocations, IAT resolution, page memory protections. |
| Rust | x64 | Beta | Standard CRT and SEH table registration handled in-memory. |
Go (gc) |
x64 | Beta | Native runtime initialization and argument forwarding. |
| C# (.NET Framework 2.0 - 4.8.1) | AnyCPU / x64 | Beta | In-process CLR hosting without temporary files. |
| C# (Modern .NET 6/8/10 / Native AOT) | x64 | Unsupported | Blocked by Microsoft apphost bundle-reading architecture. |
#include "frunner.hpp"
#include <string>
int main() {
std::string base64Payload = "TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAA...";
// Execute with arguments in silent mode
bool success = Frunner::ExecuteBase64(base64Payload, "--config client.json");
return success ? 0 : 1;
}#include "frunner.hpp"
#include <string>
int main() {
std::string base64Payload = "...";
// Pass verbose = true to view step-by-step memory mapping logs
Frunner::ExecuteBase64(base64Payload, "", true);
return 0;
}namespace Frunner {
// Execute from a raw vector of PE bytes
bool Execute(const std::vector<BYTE>& payload, const std::string& args = "", bool verbose = false);
// Execute from a Base64-encoded string
bool ExecuteBase64(const std::string& base64Payload, const std::string& args = "", bool verbose = false);
}This software is developed and distributed for educational, research, and legitimate reverse-engineering analysis purposes only. The author is not responsible for any misuse or damages caused by this program.