I'm using ReadProcessMemory
to read a process' memory. It seems like when I read across a module's end, the rest of the bytes are not read successfully. I'm also getting the following kernel error:
299: Only part of a ReadProcessMemory or WriteProcessMemory request was completed.
If I list all modules with EnumProcessModules
, none of them contain the address I'm trying to read from but Cheat Engine
can show all the memory contents just fine. Cheat Engine
says the module's size is 0xE000
and this is exactly the amount of bytes I can read before it stops and only places 0x00
bytes into the buffer which is incorrect and does not represent the actual memory contents.
Is the following code not suitable for reading across module boundaries (even if they are contiguous)?
static Memory getOutputMemory(Pointer openedProcess, long baseAddress, int length)
{
val outputMemory = new Memory(length);
val intByReference = new IntByReference();
if (!MY_KERNEL_32.ReadProcessMemory(openedProcess, baseAddress,
outputMemory, (int) outputMemory.size(), intByReference))
{
checkForKernelError();
}
return outputMemory;
}
It turns out, reading memory pages individually is how to do it e.g. like the following code:
public byte[] readBytes(long address, int length)
{
val byteBuffer = allocate(length);
var totalRemainingLength = length;
var currentAddress = address;
while (totalRemainingLength > 0)
{
val memoryBasicInformation = new MEMORY_BASIC_INFORMATION();
val process = new HANDLE(processHandle);
val pointer = new Pointer(currentAddress);
val memoryPageQueryResult = KERNEL_32.VirtualQueryEx(process, pointer, memoryBasicInformation,
new BaseTSD.SIZE_T(memoryBasicInformation.size()));
if (memoryPageQueryResult.equals(new SIZE_T(0)))
{
throw new IllegalStateException("Memory not contiguous");
}
val memoryPageBaseAddress = nativeValue(memoryBasicInformation.baseAddress);
val memoryPageSize = memoryBasicInformation.regionSize.longValue();
val memoryPageEndAddress = memoryPageBaseAddress + memoryPageSize;
val remainingMemoryPageBytes = memoryPageEndAddress - address;
val currentLength = (int) min(totalRemainingLength, remainingMemoryPageBytes);
val outputMemory = getOutputMemory(processHandle, currentAddress, currentLength);
val byteArray = outputMemory.getByteArray(0, currentLength);
byteBuffer.put(byteArray);
currentAddress += currentLength;
totalRemainingLength -= currentLength;
}
return byteBuffer.array();
}
static Memory getOutputMemory(Pointer openedProcess, long baseAddress, int length)
{
val outputMemory = new Memory(length);
val intByReference = new IntByReference();
if (!MY_KERNEL_32.ReadProcessMemory(openedProcess, baseAddress,
outputMemory, (int) outputMemory.size(), intByReference))
{
checkForKernelError();
}
return outputMemory;
}