Skip to content

Instantly share code, notes, and snippets.

@stevemk14ebr
Created May 5, 2021 14:30
Show Gist options
  • Save stevemk14ebr/ae240f47510198657028fab8018ec4f0 to your computer and use it in GitHub Desktop.
Save stevemk14ebr/ae240f47510198657028fab8018ec4f0 to your computer and use it in GitHub Desktop.
VirtualAlloc2 Bounded Allocation
// Alloc2Test.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <Windows.h>
#include <string>
#include <assert.h>
static inline char* AlignUpwards(const char* stack, size_t align) {
assert(align > 0 && (align & (align - 1)) == 0); /* Power of 2 */
assert(stack != 0);
auto addr = reinterpret_cast<uintptr_t>(stack);
if (addr % align != 0)
addr += align - addr % align;
assert(addr >= reinterpret_cast<uintptr_t>(stack));
return reinterpret_cast<char*>(addr);
}
static inline char* AlignDownwards(const char* stack, size_t align) {
assert(align > 0 && (align & (align - 1)) == 0); /* Power of 2 */
assert(stack != 0);
auto addr = reinterpret_cast<uintptr_t>(stack);
addr -= addr % align;
assert(addr <= reinterpret_cast<uintptr_t>(stack));
return reinterpret_cast<char*>(addr);
}
// based on: https://stackoverflow.com/questions/54223343/virtualalloc2-with-memextendedparameteraddressrequirements-always-produces-error
uint64_t boundAlloc(uint64_t min, uint64_t max, uint64_t size)
{
MEM_ADDRESS_REQUIREMENTS addressReqs = { 0 };
MEM_EXTENDED_PARAMETER param = { 0 };
addressReqs.Alignment = 0; // any alignment
addressReqs.LowestStartingAddress = (PVOID)min; // PAGE_SIZE aligned
addressReqs.HighestEndingAddress = (PVOID)(max - 1); // PAGE_SIZE aligned, exclusive so -1
param.Type = MemExtendedParameterAddressRequirements;
param.Pointer = &addressReqs;
auto pVirtualAlloc2 = (decltype(&::VirtualAlloc2))GetProcAddress(LoadLibrary(L"kernelbase.dll"), "VirtualAlloc2");
return (uint64_t)pVirtualAlloc2(
GetCurrentProcess(), (PVOID)0,
size,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE,
&param, 1);
}
int main()
{
auto calc_2gb_below = [](uint64_t address) -> uint64_t
{
return (address > (uint64_t)0x7ff80000) ? address - 0x7ff80000 : 0x80000;
};
auto calc2gb_above = [](uint64_t address) -> uint64_t
{
return (address < (uint64_t)0xffffffff80000000) ? address + 0x7ff80000 : (uint64_t)0xfffffffffff80000;
};
uint64_t randAddr = (uint64_t)new char[64];
uint64_t max = (uint64_t)AlignDownwards((char*)calc2gb_above(randAddr), 0x10000);
uint64_t min = (uint64_t)AlignDownwards((char*)calc_2gb_below(randAddr), 0x10000);
printf("Pivot %I64X +-2GB_Range: [%I64X, %I64X)\n", randAddr, min, max);
uint64_t alloc = boundAlloc(min, max, 0x10000);
printf("Alloc %I64X\n", alloc);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment