-
Notifications
You must be signed in to change notification settings - Fork 498
Description
This isn't a direct error/bug however I'm just unsure on how to achieve what im wanting to with VMM.
What I want: To find an address within a RW allocation that is not inside a section as quick as possible similar to something like CheatEngine's timing.
I've been using your project for a while and have noticed that VAD is sometimes missing an allocation that virtualquery finds, I'm not familiar with the backend of the VirtualQuery API's but trying to use your PTE map has warranted more consistent results however it still clumps allocations together and has a dodgy way of identifying flags leading to me spending way longer iterating trying to scan memory.
I'm just curious if you have functions/enums in place that I haven't found when reading in the documentation to do what I'm doing more efficiently
PVMMDLL_MAP_PTE pte_map = nullptr;
if (!VMMDLL_Map_GetPteU(device_handle, process_id, false, &pte_map)) {
return false;
}
PVMMDLL_MAP_VAD vad_map = NULL;
if (!VMMDLL_Map_GetVadW(device_handle, process_id, false, &vad_map)) {
return false;
}
auto get_type = [](const VMMDLL_MAP_PTEENTRY& e) {
if (!e.uszText || !*e.uszText) return DWORD(MEM_PRIVATE);
std::string s = e.uszText;
if (s.size() >= 4 &&
(s.ends_with(".exe") || s.ends_with(".dll"))) return DWORD(MEM_IMAGE);
return DWORD(MEM_MAPPED);
};
auto get_state = [](const VMMDLL_MAP_PTEENTRY& e) {
return (e.cSoftware == e.cPages)
? DWORD(MEM_RESERVE)
: DWORD(MEM_COMMIT);
};
auto get_protection = [](uint64_t f) {
bool w = f & 0x2;
bool nx = f & 0x8000000000000000;
if (!w && nx) return DWORD(PAGE_NOACCESS);
if (!w && !nx) return DWORD(PAGE_READONLY);
if (w && nx) return DWORD(PAGE_READWRITE);
return DWORD(PAGE_READWRITE);
};
// i use vad here to order the vad's first as majority of the time they contain the value im searching for.
auto find_surrounding_vad = [&vad_map](uint64_t start) -> PVMMDLL_MAP_VADENTRY {
for (DWORD i = 0; i < vad_map->cMap; i++) {
PVMMDLL_MAP_VADENTRY vad_entry = &vad_map->pMap[i];
if (vad_entry) {
if (vad_entry->vaStart <= start && vad_entry->vaEnd > start) {
return vad_entry;
}
}
}
return nullptr;
};
for (DWORD i = 0; i < pte_map->cMap; i++) {
PVMMDLL_MAP_PTEENTRY entry = &pte_map->pMap[i];
// We wanna ignore any allocs from the module space
if (entry->vaBase > 0x700000000000) {
continue;
}
PVMMDLL_MAP_VADENTRY vad_entry = find_surrounding_vad(entry->vaBase);
ProcessAllocationData data;
data.base_address = entry->vaBase;
data.size = entry->cPages * 0x1000;
data.protection = get_protection(entry->fPage);
data.state = get_state(*entry);
data.type = get_type(*entry);
data.committed_pages = entry->cPages - entry->cSoftware;
I believe I'm doing the scanning as efficiently as possible so my only solution is to filter the allocations im scanning even more.
my scanning code:
for (const auto& alloc : allocs) {
const size_t size = alloc.Size();
if (size < 0x2000 || size > kMaxAllocSize) {
continue;
}
if (!alloc.IsCommitted() ||
alloc.IsReserved() ||
!alloc.IsPrivate() ||
alloc.Protection() != PAGE_READWRITE) {
continue;
}
process()->ReadMemory(alloc.Begin(), buf.data(), size);
for (uint32_t offset = 0; offset < size; offset += 8) {
if (*reinterpret_cast<uint64_t*>(buf.data() + offset) == rdata_constant_addr_) {
return reinterpret_cast<ObjectManager*>(alloc.Begin() + offset - rdata_constant_offset_);
}
}
}Ps. I've used your regular Mem search api however that was also very slow once there was a lot of allocations, whereas something like VirtualQuery would find it quicker.