2

I've been trying to create my own memory reader in C# based on a couple of articles I've seen on CodeProject. I got everything working as I would have liked when compiled for 32-bit Windows, but the issues began when I tried to convert over to a 64-bit build.

I was able to get VirtualQueryEx to work in a 64-bit C++ test project, where the MEMORY_BASIC_INFORMATION is already defined, and the BaseAddress member is a PVOID.

When I tried to move over to C#, I have to define MEMORY_BASIC_INFORMATION myself as indicated in the CodeProject example above that I am using as guidance.

The below code works for applications that have small memory profiles, but for larger applications, the MI.BaseAddress variable below seems to truncate to 2,147,356,672, and the program is stuck in an infinite loop, where currentAddress is always equal to MI.BaseAddress + MI.RegionSize (before casting to ulong).

Any guidance would be greatly appreciated. Thank you!

public struct MEMORY_BASIC_INFORMATION
{
    public ulong BaseAddress;
    public ulong AllocationBase;
    public int AllocationProtect;
    public ulong RegionSize;
    public int State;
    public ulong Protect;
    public ulong Type;
}

-

[DllImport("kernel32.dll", SetLastError=true)]
static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);

-

public void getBlocks(int pid)
{
    totalBytes = 0;
    if (addresses != null)
        addresses = null;
    addresses = new List<UIntPtr>();
    if (sizes != null)
        sizes = null;
    sizes = new List<UInt64>();
    setPID(pid);
    getHandle();

    ulong currentAddress;
    ulong maxAddress;

    SYSTEM_INFO SI;
    GetSystemInfo(out SI);
    maxAddress = (ulong)SI.maximumApplicationAddress;
    currentAddress = (ulong)SI.minimumApplicationAddress;

    MEMORY_BASIC_INFORMATION MI;

    while (currentAddress < maxAddress)
    {
        VirtualQueryEx(hProc, (IntPtr)currentAddress, out MI, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)));
        if (MI.State == MEM_COMMIT)
        {
            totalBytes += (ulong)MI.RegionSize;
        }
        currentAddress = (ulong)MI.BaseAddress + (ulong)MI.RegionSize;
    }
Chris Mantle
  • 6,595
  • 3
  • 34
  • 48
Oblag
  • 21
  • 1
  • 2
  • Your MEMORY_BASIC_INFORMATION does not look good. http://www.pinvoke.net/default.aspx/Structures/MEMORY_BASIC_INFORMATION.html – usr Jun 30 '14 at 10:29
  • Protect and Type are *int*, not *ulong*. Do favor using *IntPtr* for the fields that you now declared *ulong*, that way your code will work in both 32-bit and 64-bit mode. – Hans Passant Jun 30 '14 at 11:01
  • @usr: Thank you, from that page I was able to find sample code that fixed my problem. [link]http://www.pinvoke.net/default.aspx/kernel32/VirtualQueryEx.html – Oblag Jul 01 '14 at 17:36

0 Answers0