Skip to main content

Overview

The allocator::heap policy allocates memory for syscall stubs using a private heap created with the HEAP_CREATE_ENABLE_EXECUTE flag. This provides executable memory in a separate heap, isolated from the process’s default heap.

Method Signatures

allocate
static bool
Creates a private executable heap and allocates memory for syscall stubs
static bool allocate(
    size_t uRegionSize,
    const std::span<const uint8_t> vecBuffer,
    void*& pOutRegion,
    HANDLE& hOutHeapHandle
)
return
bool
Returns true on successful allocation, false on failure
release
static void
Destroys the private heap
static void release(void* /*region*/, HANDLE hHeapHandle)

Implementation Details

The allocation process:
  1. Create a private heap with HEAP_CREATE_ENABLE_EXECUTE | HEAP_GROWABLE
  2. Allocate memory from the heap using RtlAllocateHeap
  3. Copy the syscall stubs into the allocated memory
  4. Return the allocation address and heap handle
The heap handle must be preserved for cleanup. The Manager class stores it internally and passes it to release() in the destructor.

Source Code

From syscall.hpp:167-209:
struct heap
{
    static bool allocate(size_t uRegionSize, const std::span<const uint8_t> vecBuffer,
                        void*& pOutRegion, HANDLE& hOutHeapHandle)
    {
        HMODULE hNtdll = native::getModuleBase(hashing::calculateHash("ntdll.dll"));
        if (!hNtdll)
            return false;

        auto fRtlCreateHeap = reinterpret_cast<native::RtlCreateHeap_t>(
            native::getExportAddress(hNtdll, SYSCALL_ID("RtlCreateHeap")));
        auto fRtlAllocateHeap = reinterpret_cast<native::RtlAllocateHeap_t>(
            native::getExportAddress(hNtdll, SYSCALL_ID("RtlAllocateHeap")));
            
        if (!fRtlCreateHeap || !fRtlAllocateHeap)
            return false;

        hOutHeapHandle = fRtlCreateHeap(
            HEAP_CREATE_ENABLE_EXECUTE | HEAP_GROWABLE,
            nullptr, 0, 0, nullptr, nullptr
        );
        if (!hOutHeapHandle)
            return false;

        pOutRegion = fRtlAllocateHeap(hOutHeapHandle, 0, uRegionSize);
        if (!pOutRegion) {
            release(nullptr, hOutHeapHandle);
            hOutHeapHandle = nullptr;
            return false;
        }

        std::copy_n(vecBuffer.data(), uRegionSize, static_cast<uint8_t*>(pOutRegion));
        return true;
    }

    static void release(void* /*region*/, HANDLE hHeapHandle)
    {
        if (hHeapHandle) {
            HMODULE hNtdll = native::getModuleBase(hashing::calculateHash("ntdll.dll"));
            if (!hNtdll)
                return;

            auto fRtlDestroyHeap = reinterpret_cast<native::RtlDestroyHeap_t>(
                native::getExportAddress(hNtdll, SYSCALL_ID("RtlDestroyHeap")));
            if (fRtlDestroyHeap)
                fRtlDestroyHeap(hHeapHandle);
        }
    }
};

Usage Example

#include <syscalls-cpp/syscall.hpp>

// Use with gadget generation on x64
#if SYSCALL_PLATFORM_WINDOWS_64
SyscallHeapGadget syscallManager;
if (!syscallManager.initialize()) {
    std::cerr << "Failed to initialize with heap allocator\n";
    return 1;
}
#endif

// Or compose manually
using HeapDirectManager = syscall::Manager<
    syscall::policies::allocator::heap,
    syscall::policies::generator::direct
>;

HeapDirectManager manager;
manager.initialize();

Security Properties

Isolation

Syscall stubs are isolated in a separate heap, distinct from the process’s default heap and other allocations.

Executable

The HEAP_CREATE_ENABLE_EXECUTE flag allows code execution directly from heap memory without additional protection changes.

Trade-offs

AspectDescription
SecurityMedium—executable but mutable
PerformanceFast allocation (single heap operation)
ComplexitySimple, straightforward process
CompatibilityWindows 2000+
Memory ManagementAutomatic cleanup via heap destruction
While faster than section-based allocation, heap memory can still be modified after allocation, making it less secure than SEC_NO_CHANGE sections.

See Also

allocator::section

Immutable section-based allocation

allocator::memory

Virtual memory allocation

Policy Composition

Learn how to combine policies

Build docs developers (and LLMs) love