// Memory access check staticboolIsMemoryReadable(uintptr_t base) { size_t length = sizeof(uintptr_t); constexprsize_t read_access = (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); //structure to pass to virtual query which will be populated with the page's information MEMORY_BASIC_INFORMATION mbi = { 0 };
//virtual query returns information on a page //if you don't know what a page is , it's basically a contiguous block of memory //query for information starting at base if (VirtualQuery(reinterpret_cast<void*>(base), &mbi, sizeof(mbi))) { //check read protections. if the page has one of the listed access protections, we can successfully read from it if (!(mbi.Protect & read_access)) returnfalse;
//When a process COMMITS a region of virtual memory, the operating system guarantees that it can maintain all the data //the process stores in the memory either in physical memory or on disk. //so check for MEM_COMMIT because this means the page is able to store data //if this is MEM_RESERVE OR MEM_FREE we don't want to attempt a read if (!(mbi.State & MEM_COMMIT)) returnfalse;
//make sure the page is not guarded and has access. attempts to read or access these kinds of pages will result in an access violation if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) returnfalse;
//get the start and end of the page constauto start = reinterpret_cast<uintptr_t>(mbi.BaseAddress); constautoend = static_cast<uintptr_t>(start + mbi.RegionSize);
//check if our memory is within the readable region. return (base >= start) && ((base + length) <= end); } returnfalse; }