Skip to content

Commit

Permalink
improvements to VirtualQueryEx
Browse files Browse the repository at this point in the history
Will now cache & re-scan the memory every 1000 ticks.
  • Loading branch information
Metick committed Apr 8, 2024
1 parent 39186e1 commit 5e4f167
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 53 deletions.
3 changes: 3 additions & 0 deletions plugin/CheatEngine/cepluginsdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,13 @@ typedef struct _ExportedFunctions
PVOID WaitForProcessListData; // ...
PVOID GetProcessNameFromID; // ...
PVOID GetProcessNameFromPEProcess; // ...

//Deprecated Kernel functions
PVOID KernelOpenProcess; // ...
PVOID KernelReadProcessMemory; // ...
PVOID KernelWriteProcessMemory; // ...
PVOID KernelVirtualAllocEx; // ...

PVOID IsValidHandle; // ...
PVOID GetIDTCurrentThread; // ...
PVOID GetIDTs; // ...
Expand Down
128 changes: 77 additions & 51 deletions plugin/Hooks/mem.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#include <list>
#include <map>

#include "hooks.h"
#include "DMALibrary/Memory/Memory.h"
#include "Memory/memmy.h"
Expand All @@ -11,29 +14,8 @@ namespace Hooks
HANDLE hk_open_process(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
{
if (mem.Init(dwProcessId))
{
PVMMDLL_MAP_VAD vads;
memoryMap.clear();
vad_infos.clear();

if (!VMMDLL_Map_GetVadW(mem.vHandle, mem.current_process.PID, true, &vads))
return false;

std::vector<vad_info> vad_infos;
for (size_t i = 0; i < vads->cMap; i++)
{
auto vad = vads->pMap[i];
vad_infos.push_back(vad_info(vad.wszText, vad.vaStart, vad.vaEnd, vad));
}

for (size_t i = 0; i < vad_infos.size(); i++)
{
size_t regionSize = vad_infos[i].get_end() - vad_infos[i].get_start() + 1;
//printf("Region: %s, Start: %llx, End: %llx, Size: %llx\n", vad_infos[i].get_name().c_str(), vad_infos[i].get_start(), vad_infos[i].get_end(), regionSize);
memoryMap.push_back(c_memory_region<vad_info>(vad_infos[i], vad_infos[i].get_start(), regionSize));
}
return (HANDLE)0x69;
}

return false;
}

Expand All @@ -47,42 +29,86 @@ namespace Hooks
return mem.Write((UINT64)lpBaseAddress, lpBuffer, nSize);
}

//Memory in VirtualQuery Is always rounded down, getMemoryRegionContaining will find the nearest (rounded down) region that contains the address.
//or if it's equal return the exact region.
SIZE_T hk_virtual_query(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)
std::list<c_memory_region<vad_info>> get_memory_region()
{
MEMORY_BASIC_INFORMATION meminfo;
uintptr_t address = reinterpret_cast<uintptr_t>(lpAddress);
auto it = std::lower_bound(memoryMap.begin(), memoryMap.end(), address,
std::list<c_memory_region<vad_info>> result = { };
PVMMDLL_MAP_VAD vads = nullptr;
memoryMap.clear();
vad_infos.clear();

if (!VMMDLL_Map_GetVadW(mem.vHandle, mem.current_process.PID, true, &vads))
return { };

std::vector<vad_info> vad_infos;
for (size_t i = 0; i < vads->cMap; i++)
{
auto vad = vads->pMap[i];
vad_infos.push_back(vad_info(vad.wszText, vad.vaStart, vad.vaEnd, vad));
}

for (size_t i = 0; i < vad_infos.size(); i++)
{
size_t regionSize = vad_infos[i].get_end() - vad_infos[i].get_start() + 1;
result.push_back(c_memory_region<vad_info>(vad_infos[i], vad_infos[i].get_start(), regionSize));
}
return result;
}

std::map<int, std::pair<uint64_t, std::list<c_memory_region<vad_info>>>> region_cache;

bool VirtualQueryImpl_(uintptr_t lpAddress, c_memory_region<vad_info>* ret)
{
if (region_cache.find(mem.current_process.PID) != region_cache.end())
{
auto&& [time, region] = region_cache[mem.current_process.PID];
if (GetTickCount() - time > 1000)
{
auto&& new_region = get_memory_region();
region_cache.erase(mem.current_process.PID);
region_cache.insert({mem.current_process.PID, {GetTickCount(), new_region}});
}
}
else
{
auto&& new_region = get_memory_region();
region_cache.insert({mem.current_process.PID, std::pair(GetTickCount(), new_region)});
}
auto regions = region_cache[mem.current_process.PID].second;

auto it = std::lower_bound(regions.begin(), regions.end(), lpAddress,
[](const c_memory_region<vad_info>& region, uintptr_t addr)
{
return region.get_region_start() <= addr;
});
if (it == regions.end())
return false;
*ret = *it;
return true;
}

if (it == memoryMap.end())
{
//Memory in VirtualQuery Is always rounded down, getMemoryRegionContaining will find the nearest (rounded down) region that contains the address.
//or if it's equal return the exact region.
SIZE_T hk_virtual_query(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)
{
MEMORY_BASIC_INFORMATION meminfo = { };
c_memory_region<vad_info> info;
if (!Hooks::VirtualQueryImpl_(reinterpret_cast<uintptr_t>(lpAddress), &info))
return 0;
}
//printf("[%llx] Found region: %llx - %llx\n", address, it->get_region_start(), it->get_region_end());
if (it->get_region_size() > 0)
{
//We have Protection hardcoded rn, because we're DMA and we can read all pages. uncomment the line in get_protection & comment the PAGE_READWRITE to use the real protection that the page has.
auto found_vad = it->get_object();
auto rangeStart = it->get_region_start();
auto rangeEnd = it->get_region_end();
auto size = rangeEnd - rangeStart + 1;
meminfo.BaseAddress = reinterpret_cast<PVOID>(rangeStart);
meminfo.AllocationBase = reinterpret_cast<PVOID>(rangeStart);
meminfo.AllocationProtect = found_vad.get_protection();
meminfo.RegionSize = size;
meminfo.State = found_vad.get_state();
meminfo.Protect = found_vad.get_protection();
meminfo.Type = found_vad.get_type();
meminfo.PartitionId = 0;
memcpy(lpBuffer, &meminfo, sizeof(meminfo));
return sizeof(meminfo);
}

return 0;
ZeroMemory(&meminfo, sizeof(meminfo));
auto found_vad = info.get_object();
auto rangeStart = info.get_region_start();
auto rangeEnd = info.get_region_end();
auto size = rangeEnd - rangeStart + 1;
meminfo.BaseAddress = reinterpret_cast<PVOID>(rangeStart);
meminfo.AllocationBase = reinterpret_cast<PVOID>(rangeStart);
meminfo.AllocationProtect = found_vad.get_protection();
meminfo.RegionSize = size;
meminfo.State = found_vad.get_state();
meminfo.Protect = found_vad.get_protection();
meminfo.Type = found_vad.get_type();
meminfo.PartitionId = 0;
memcpy(lpBuffer, &meminfo, sizeof(meminfo));
return sizeof(meminfo);
}
}
4 changes: 2 additions & 2 deletions plugin/Memory/vad.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ class vad_info

uint32_t get_protection()
{
return PAGE_READWRITE;
//return _protection;
//return PAGE_READWRITE;
return _protection;
}

uint32_t get_image()
Expand Down

0 comments on commit 5e4f167

Please sign in to comment.