Skip to content

Instantly share code, notes, and snippets.

@Lima-X
Last active August 27, 2021 15:05
Show Gist options
  • Save Lima-X/d3a7a77af09615cbdd8800b25053dbe6 to your computer and use it in GitHub Desktop.
Save Lima-X/d3a7a77af09615cbdd8800b25053dbe6 to your computer and use it in GitHub Desktop.
MemeAllocator a new futuristic type of memory allocation based on dynamically generated images, ok fuck it, this was a very dumb thing to design
// This thing is based on a stupid idea that came after a bet that i had with @LapysDev
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <cstdint>
constexpr uint32_t RoundUpToMulOfPow2(
_In_ uint32_t Number,
_In_ int32_t Multiplier
) {
return (Number + (Multiplier - 1)) & -Multiplier;
}
class MemeAllocator {
public:
MemeAllocator()
{
auto& DosHeader = *reinterpret_cast<IMAGE_DOS_HEADER*>(
DynamicDllImage);
DosHeader.e_magic = IMAGE_DOS_SIGNATURE;
DosHeader.e_lfanew = sizeof(IMAGE_DOS_HEADER);
auto& ImageHeader = *reinterpret_cast<IMAGE_NT_HEADERS*>(
DynamicDllImage + sizeof(IMAGE_DOS_HEADER));
ImageHeader.Signature = IMAGE_NT_SIGNATURE;
auto& FileHeader = ImageHeader.FileHeader;
FileHeader.Machine =
#if _M_X64
IMAGE_FILE_MACHINE_AMD64;
#elif _M_IX86
IMAGE_FILE_MACHINE_I386;
#endif
FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE |
IMAGE_FILE_LARGE_ADDRESS_AWARE |
IMAGE_FILE_DEBUG_STRIPPED |
IMAGE_FILE_DLL;
FileHeader.NumberOfSections = 1;
auto& OptionalHeader = ImageHeader.OptionalHeader;
OptionalHeader.Magic =
#if _M_X64
IMAGE_NT_OPTIONAL_HDR64_MAGIC;
#elif _M_IX86
IMAGE_NT_OPTIONAL_HDR32_MAGIC;
#endif
OptionalHeader.AddressOfEntryPoint = NULL;
OptionalHeader.SectionAlignment = X86PageSize;
OptionalHeader.FileAlignment = DefaultFileAlignment;
OptionalHeader.SizeOfHeaders = PhysicalImageSize;
OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_NATIVE;
OptionalHeader.NumberOfRvaAndSizes = 16;
OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT |
IMAGE_DLLCHARACTERISTICS_NO_SEH;
auto SectionHeaderTable = reinterpret_cast<IMAGE_SECTION_HEADER*>(
reinterpret_cast<uintptr_t>(&OptionalHeader) + sizeof(IMAGE_OPTIONAL_HEADER));
memcpy(SectionHeaderTable[0].Name, ".bss", 4);
SectionHeaderTable[0].Characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
GetTempPathA(MAX_PATH,
TempFileDirectory);
}
long MemeAllocate(
_Inout_opt_ void*& DesiredBlockAddress,
_In_ size_t MemoryBlockSize,
_In_opt_ uint32_t MemoryProtection = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
) {
// Generate Dll with memory requirements
{
auto& ImageHeader = *reinterpret_cast<IMAGE_NT_HEADERS*>(
DynamicDllImage + sizeof(IMAGE_DOS_HEADER));
auto& FileHeader = ImageHeader.FileHeader;
auto& OptionalHeader = ImageHeader.OptionalHeader;
const auto DesiredAddress = reinterpret_cast<uintptr_t>(DesiredBlockAddress);
FileHeader.Characteristics &= ~IMAGE_FILE_RELOCS_STRIPPED;
OptionalHeader.DllCharacteristics &= ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
if (DesiredAddress) {
OptionalHeader.ImageBase = DesiredAddress &
~(AllocationGranularity - 1);
if (DesiredAddress < OptionalHeader.ImageBase + OptionalHeader.SectionAlignment)
OptionalHeader.ImageBase -= AllocationGranularity;
FileHeader.Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
} else
OptionalHeader.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
auto SectionHeaderTable = reinterpret_cast<IMAGE_SECTION_HEADER*>(
reinterpret_cast<uintptr_t>(&OptionalHeader) + sizeof(IMAGE_OPTIONAL_HEADER));
SectionHeaderTable[0].VirtualAddress = DesiredAddress ?
DesiredAddress -
OptionalHeader.ImageBase &
OptionalHeader.SectionAlignment :
OptionalHeader.SectionAlignment;
SectionHeaderTable[0].Misc.VirtualSize = (DesiredAddress ?
(DesiredAddress -
OptionalHeader.ImageBase -
SectionHeaderTable[0].VirtualAddress) +
MemoryBlockSize : 0) + MemoryBlockSize;
SectionHeaderTable[0].Characteristics &= ~(IMAGE_SCN_MEM_READ |
IMAGE_SCN_MEM_WRITE |
IMAGE_SCN_MEM_EXECUTE);
SectionHeaderTable[0].Characteristics |= MemoryProtection;
OptionalHeader.SizeOfImage = RoundUpToMulOfPow2(
(DesiredAddress ?
DesiredAddress -
OptionalHeader.ImageBase :
SectionHeaderTable[0].VirtualAddress) +
MemoryBlockSize,
OptionalHeader.SectionAlignment);
OptionalHeader.SizeOfUninitializedData = SectionHeaderTable[0].Misc.VirtualSize;
}
// WriteFile to temporary file path
char TempFilePath[MAX_PATH];
{
auto Status = GetTempFileNameA(TempFileDirectory,
"MemeAllocator",
0,
TempFilePath);
if (!Status)
return -1;
auto FileHandle = CreateFileA(TempFilePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
nullptr,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (FileHandle == INVALID_HANDLE_VALUE)
return -2;
unsigned long BytesWritten;
Status = WriteFile(FileHandle,
DynamicDllImage,
PhysicalImageSize,
&BytesWritten,
nullptr);
if (!Status)
return -3;
Status = SetFilePointer(FileHandle,
DefaultFileAlignment,
0,
FILE_BEGIN);
if (Status == INVALID_SET_FILE_POINTER)
return -4;
Status = SetEndOfFile(FileHandle);
if (!Status)
return -5;
CloseHandle(FileHandle);
}
// Load file and return address space
auto Module = LoadLibraryA(TempFilePath);
if (!Module)
return -6;
if (!DesiredBlockAddress)
DesiredBlockAddress = reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(Module) + X86PageSize);
// Store internal file name reference for deleting the container
auto TempFilePathLength = strlen(TempFilePath);
unsigned long OldProtect;
VirtualProtect(Module,
X86PageSize,
PAGE_READWRITE,
&OldProtect);
memcpy(reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(Module) +
PhysicalImageSize),
TempFilePath + (TempFilePathLength - 11), // Hardcoded number yeah i know but whatever
11);
return 0;
}
long MemeFree(
_In_ void* MemoryBlockAddress
) {
// Lookup Imagebase containing allocated buffer
// Calculate Dll base
const auto MemoryAddress = reinterpret_cast<uintptr_t>(MemoryBlockAddress);
auto ImageBase = MemoryAddress &
~(AllocationGranularity - 1);
if (MemoryAddress < ImageBase + X86PageSize)
ImageBase -= AllocationGranularity;
// Validate we are dealing with our image
auto& MsDosHeader = *reinterpret_cast<IMAGE_DOS_HEADER*>(
ImageBase);
if (MsDosHeader.e_magic != IMAGE_DOS_SIGNATURE &&
MsDosHeader.e_lfanew != sizeof(IMAGE_DOS_HEADER))
return -1;
auto& ImageHeader = *reinterpret_cast<IMAGE_NT_HEADERS*>(
ImageBase + sizeof(IMAGE_DOS_HEADER));
if (ImageHeader.Signature != IMAGE_NT_SIGNATURE &&
ImageHeader.OptionalHeader.Magic !=
#if _M_X64
IMAGE_NT_OPTIONAL_HDR64_MAGIC
#elif _M_IX86
IMAGE_NT_OPTIONAL_HDR32_MAGIC
#endif
) return -2;
// Unload image
char TempFilePath[MAX_PATH];
strcpy(TempFilePath, TempFileDirectory);
strcat(TempFilePath,
reinterpret_cast<char*>(
ImageBase + PhysicalImageSize));
auto Status = FreeLibrary(reinterpret_cast<HMODULE>(ImageBase));
if (!Status)
return -3;
DeleteFileA(TempFilePath);
}
private:
static constexpr size_t PhysicalImageSize = sizeof(IMAGE_DOS_HEADER) +
sizeof(IMAGE_NT_HEADERS) +
sizeof(IMAGE_SECTION_HEADER) * 1;
uint8_t DynamicDllImage[PhysicalImageSize]{};
char TempFileDirectory[MAX_PATH];
static constexpr uintptr_t AllocationGranularity = 0x10000;
static constexpr uint32_t DefaultFileAlignment = 512;
static constexpr uint32_t X86PageSize = 4096;
};
int main() {
MemeAllocator meme;
void* mem1 = nullptr;
meme.MemeAllocate(mem1, 0x30);
void* mem2 = nullptr;
meme.MemeAllocate(mem2, 0x170);
meme.MemeFree(mem1);
mem1 = nullptr;
meme.MemeAllocate(mem1, 0x1000);
meme.MemeFree(mem1);
meme.MemeFree(mem2);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment