I'm trying to read the memory about a process using C#. I take a snapshot of all the processes and then use the VirtualQueryEx and ReadProcessMemory functions to return the memory as a string so i can go through it.

The ReadProcessMemory function doesn't return anything however, i tried debugging it, but once i get to the function it causes the debugger to exit. Has anyone tried this before or know what i'm doing wrong?

Code:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Lifetime;
using System.Security.Principal;
using System.Diagnostics;
using System.Xml;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;
using System.Net;
using System.Timers;
using System.Threading;
using System.Data;
using System.Collections.Specialized;
using Microsoft.Win32;


namespace ProcT
{
    class Program
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct ProcessEntry32
        {
            public uint dwSize;
            public uint cntUsage;
            public uint th32ProcessID;
            public IntPtr th32DefaultHeapID;
            public uint th32ModuleID;
            public uint cntThreads;
            public uint th32ParentProcessID;
            public int pcPriClassBase;
            public uint dwFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string szExeFile;
        };

        [StructLayout(LayoutKind.Sequential)]
        public struct SYSTEM_INFO
        {
            public uint dwOemId;
            public uint dwPageSize;
            public uint lpMinimumApplicationAddress;
            public uint lpMaximumApplicationAddress;
            public uint dwActiveProcessorMask;
            public uint dwNumberOfProcessors;
            public uint dwProcessorType;
            public uint dwAllocationGranularity;
            public uint dwProcessorLevel;
            public uint dwProcessorRevision;
        };

        [StructLayout(LayoutKind.Sequential)]
        struct MEMORY_BASIC_INFORMATION
        {
            public IntPtr BaseAddress;
            public IntPtr AllocationBase;
            public UInt32 AllocationProtect;
            public UInt32 RegionSize;
            public UInt32 State;
            public UInt32 Protect;
            public UInt32 lType;
        };

        #region DLL Imports
        [DllImport("KERNEL32.DLL")]
        public static extern int CreateToolhelp32Snapshot(uint flags, uint processid);

        [DllImport("KERNEL32.DLL")]
        public static extern int CloseHandle(int handle); 

        [DllImport("KERNEL32.DLL")]
        public static extern int Process32First(int handle, ref ProcessEntry32 pe);

        [DllImport("KERNEL32.DLL")]
        public static extern int Process32Next(int handle, ref ProcessEntry32 pe);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int OpenProcess(int access, bool inherit, uint processId);

        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern void GetSystemInfo(ref SYSTEM_INFO SysInfo);
        
        [DllImport("kernel32.dll")]
        static extern uint VirtualQueryEx(int hProcess, int lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);

        [DllImport("Kernel32.dll")]
        public static extern bool ReadProcessMemory(int hProcess, IntPtr lpBaseAddress, out byte[] lpBuffer, UInt32 nSize, ref UInt32 lpNumberOfBytesRead);
        #endregion

        int hProcessSnap;

        public static readonly int PROCESS_VM_READ = 0x0010;
        public static readonly int PROCESS_VM_OPERATION = 0x0008;
        public static readonly int PROCESS_QUERY_INFORMATION = 0x0400;
        public static readonly uint TH32CS_SNAPPROCESS = 0x00000002;

        static void Main(string[] args)
        {
            Program p = new Program();

            StringBuilder envVars = new StringBuilder(8192 * 2);

            p.Start(envVars);
        }

        public void Start(StringBuilder envVars)
        {
            int res;

            Process[] allServers = Process.GetProcesses();

            foreach (Process serveProc in allServers)
            {
                res = MQGetEnvironmentVariables(serveProc.Id, envVars);
            }
            
        }

        public int MQGetEnvironmentVariables(int pid, StringBuilder envVars)
        {
            ProcessEntry32 pe32 = new ProcessEntry32();
            int hProcess;

            StringBuilder sb = new StringBuilder(" ", 256);

            pe32.szExeFile = sb.ToString();

            // Fill in the size of the structure before using it. 
            pe32.dwSize = 548; 

            SnapProcess();

            if (hProcessSnap == 0)
                return -9;

            int check = Process32First(hProcessSnap, ref pe32);

            if (check == 0)
            {
                CloseHandle(hProcessSnap);
                return -8;
            }

            while (check == 1)
            {
                if (pe32.th32ProcessID == pid)
                {
                    CloseHandle(hProcessSnap);                    
                    
                    hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, false, pe32.th32ProcessID);

                    if (hProcess != 0)
                    {                     
                        GetEnvironment(hProcess, envVars);
                        return 0;
                    }
                }

                check = Process32Next(hProcessSnap, ref pe32);
            }

            CloseHandle(hProcessSnap);

            return 0; 
        }

        public int SnapProcess()
        {            
            if (hProcessSnap != 0)
                CloseHandle(hProcessSnap);
            
            hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
            
            if (hProcessSnap == 0)
                return -9;
            else
                return 0;         
        }
        
        public void GetEnvironment(int hProcess, StringBuilder envVars)
        {            
            SYSTEM_INFO sysInfo = new SYSTEM_INFO();
            MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION();

            GetSystemInfo(ref sysInfo);
            
            byte[] bBuffer = new byte[sysInfo.dwPageSize * 2];
            UInt32 lpNumberOfBytesRead = 0;

            byte bPos;

            if (sysInfo.dwPageSize != 0)
            {
                VirtualQueryEx(hProcess, 0x00010000, out mbi, Marshal.SizeOf(mbi));

                if (VirtualQueryEx(hProcess, 0x00010000, out mbi, Marshal.SizeOf(mbi)) != 0)
                {                    
                    if (ReadProcessMemory(hProcess, mbi.BaseAddress, out bBuffer, sysInfo.dwPageSize, ref lpNumberOfBytesRead))
                    {
                        //bPos = bBuffer + (byte)((UInt32)0x00010000 - (UInt32)mbi.BaseAddress);
                    }                    
                }
            }

        }
    }
}