Last active
August 27, 2021 15:05
-
-
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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