Persistent In-Memory Module Loading: Reducing Post-Exploitation Footprint with ZAIUX® Framework

August 2026

Introduction

In modern red team engagements, post-exploitation is where operations get noisy. Every time an operator executes a post-exploitation module, the conventional approach follows a well-known pattern: allocate new memory, write the module, adjust memory protections, execute, capture output, and finally release the memory. This sequence, repeated dozens of times in a single session, creates a predictable telemetry trace that EDR solutions are specifically designed to catch.
With the latest update to ZAIUX® Framework, we are introducing Persistent In-Memory Module Loading, a capability that allows operators to load ZOF (Zaiux-Object-Files) modules into the implant’s process memory once, keep them encrypted at rest, and execute them repeatedly without ever allocating new memory regions. When a module is no longer needed, it can be explicitly unloaded.

The Problem: Repetitive allocations are a detection goldmine

To understand why this feature matters, we need to look at what happens under the hood during traditional COFF execution and why EDR solutions are effective at flagging it.
Each time an operator runs a post-exploitation module through a standard COFF loader, the following sequence of operations takes place inside the target process:
  1. NtAllocateVirtualMemory is called once for the function-map table and once per COFF section (.text, .data, .rdata, etc.)
  2. The raw section bytes are copied into the freshly allocated regions
  3. Relocations and symbol resolution are processed
  4. NtProtectVirtualMemory is called to transition the ‘.text’ section from ‘PAGE_READWRITE’ to ‘PAGE_EXECUTE_READ’
  5. The entry point is called
  6. Output is captured
  7. Every allocated region is freed via NtFreeVirtualMemory
This is a straight-forward lifecycle: allocate, use, destroy. But the problem lies in repetition.
Consider a realistic scenario: an operator needs to repeatedly query Active Directory for different attributes. Each invocation triggers the full cycle above. Over the course of an engagement, this can produce hundreds of allocation-protect-execute-free sequences in a short time window, all within the same process.

What EDRs See

EDR solutions have multiple vantage points for observing this behavior:
  1. Usermode hooks on critical NT APIs (NtAllocateVirtualMemory, NtProtectVirtualMemory, NtFreeVirtualMemory) allow the EDR to intercept each allocation, protection change, and free operation. Even when these hooks are bypassed through indirect syscalls or unhooking, the kernel-level telemetry remains.
  2. Kernel callbacks and ETW (Event Tracing for Windows) provide an independent layer of visibility. The kernel can observe:
    – Memory allocation events: new committed regions appearing in the process address space
    – Protection change events: the ‘RW ⇒ RX’ transition on the ‘.text’ section is a high-signal indicator
    – The allocation pattern itself: multiple ‘MEM_COMMIT | MEM_RESERVE’ calls in rapid succession for small, similarly-sized regions
  3. Memory scanning is often triggered by behavioral signals. When an EDR observes a suspicious pattern (e.g., a new RX region that didn’t come from a loaded DLL), it may perform a synchronous or asynchronous scan (mostly yara) of the process memory looking for known signatures.
  4. Behavioral correlation ties these signals together. A single NtAllocateVirtualMemory call is not inherently suspicious. But when the EDR’s ring-buffer correlates dozens of allocation-protect-execute-free cycles happening from the same thread, in the same process, over a short window, it paints a clear picture of in-memory module loading: a behavior that is almost exclusively associated with offensive tooling.

The Solution: Load Once, Execute Many, Unload When Done

The core insight behind Persistent In-Memory Module Loading is simple: if the module doesn’t change between executions, there is no reason to allocate and free memory every time. Instead, we:
  1. Load the ZOF binary into a persistent memory region once.
  2. Encrypt it at rest.
  3. On each execution: decrypt ⇒ set proper protections ⇒ execute ⇒ restore to RW and re-encrypt
  4. Optional: unload explicitly when the module is no longer needed
The critical difference is that steps 3 is performed without any new memory allocation, the raw COFF binary persists in an encrypted state between executions:

Introducing coffee load, coffee mem, and coffee unload

With the latest ZAIUX® Framework release, we introduce Persistent In-Memory Module Loading, a new execution model for ZOF (Zaiux Object Files) that decouples memory allocation from module execution through three new commands: coffee load, coffee mem, and coffee unload.

coffee load <file> <alias> uploads a ZOF binary into the implant’s process memory under a unique operator-defined alias. The raw COFF is written into a single PAGE_READWRITE  region, immediately encrypted at rest, and tracked in a persistent linked list. From this point forward, the module exists in memory as high-entropy data indistinguishable from ordinary heap content: no executable permissions, no recognizable COFF structures.

coffee mem <alias> [args...] executes a previously loaded module without allocating new memory for the binary itself. The encrypted blob is decrypted in-place, sections and relocations are processed onto pre-allocated regions within the same allocation, the ‘.text’ section is briefly transitioned to PAGE_EXECUTE_READ for execution, output is captured, and the entire region is restored to PAGE_READWRITE and re-encrypted. Called without arguments, coffee mem lists all currently loaded modules with their alias, address, and size.

coffee unload <alias> performs a clean removal: the encrypted region is zeroed, freed via NtFreeVirtualMemory and the tracking node is unlinked from the list.

The operational benefit is a direct reduction in observable telemetry. A module executed 20 times through the traditional coffee command produces 100 NtAllocateVirtualMemory and 100 NtFreeVirtualMemory calls. The same 20 executions through coffee load + coffee mem produce exactly 1 allocation and 1 free, the rest happens on already-committed memory. This collapses the behavioral signal that EDR correlation engines rely on: fewer allocation events, no repeated RW-to-RX transitions on new regions, and no allocation-free cycles clustering in sliding detection windows.

Conclusion

Persistent In-Memory Module Loading is not a revolutionary concept in isolation, the individual techniques are established patterns. What makes it effective is the combination and the operational discipline it enables: load what you need, execute it as many times as necessary, and unload it when you’re done; all while minimizing the telemetry footprint that EDR solutions depend on for detection.
By reducing the number of memory allocation and deallocation events by an order of magnitude during active post-exploitation, operators gain a meaningfully quieter operational profile. The encrypted-at-rest storage adds defense-in-depth against memory scanning and forensic recovery. And the explicit load/unload lifecycle gives operators fine-grained control over what exists in memory at any point during an engagement.
The feature is available now in ZAIUX® Framework. Are you curious to see it in action?