Page 1 of 1

C# - Reading Memory from a process

Posted: Sun Oct 19, 2008 9:38 am
by zer0
Hey I'm using C# to try and read process memory. For some reason though, no bytes are read because in ReadProcessMemory(), ptrBytesRead is always 0. I can't figure it out, I'm hoping someone here might be able to point out the issue, since a few of you are much more familiar with hooking processes.

ProcessMemoryReader.cs

Code: Select all

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ProcessMemoryReaderLib
{
    /// <summary>
    /// ProcessMemoryReader is a class that enables direct reading a process memory
    /// </summary>
    class ProcessMemoryReaderApi
    {
        // constants information can be found in <winnt.h>
        [Flags]
        public enum ProcessAccessType
        {
            PROCESS_TERMINATE = (0x0001),
            PROCESS_CREATE_THREAD = (0x0002),
            PROCESS_SET_SESSIONID = (0x0004),
            PROCESS_VM_OPERATION = (0x0008),
            PROCESS_VM_READ = (0x0010),
            PROCESS_VM_WRITE = (0x0020),
            PROCESS_DUP_HANDLE = (0x0040),
            PROCESS_CREATE_PROCESS = (0x0080),
            PROCESS_SET_QUOTA = (0x0100),
            PROCESS_SET_INFORMATION = (0x0200),
            PROCESS_QUERY_INFORMATION = (0x0400)
        }

        // function declarations are found in the MSDN and in <winbase.h>

        //      HANDLE OpenProcess(
        //         DWORD dwDesiredAccess,  // access flag
        //         BOOL bInheritHandle,    // handle inheritance option
        //         DWORD dwProcessId       // process identifier
        //         );
        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);

        //      BOOL CloseHandle(
        //         HANDLE hObject   // handle to object
        //         );
        [DllImport("kernel32.dll")]
        public static extern Int32 CloseHandle(IntPtr hObject);

        //      BOOL ReadProcessMemory(
        //         HANDLE hProcess,              // handle to the process
        //         LPCVOID lpBaseAddress,        // base of memory area
        //         LPVOID lpBuffer,              // data buffer
        //         SIZE_T nSize,                 // number of bytes to read
        //         SIZE_T * lpNumberOfBytesRead  // number of bytes read
        //         );
        [DllImport("kernel32.dll")]
        public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

        //      BOOL WriteProcessMemory(
        //         HANDLE hProcess,                // handle to process
        //         LPVOID lpBaseAddress,           // base of memory area
        //         LPCVOID lpBuffer,               // data buffer
        //         SIZE_T nSize,                   // count of bytes to write
        //         SIZE_T * lpNumberOfBytesWritten // count of bytes written
        //         );
        [DllImport("kernel32.dll")]
        public static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten);


    }

    public class ProcessMemoryReader
    {

        public ProcessMemoryReader()
        {
        }

        /// <summary>   
        /// Process from which to read      
        /// </summary>
        public Process ReadProcess
        {
            get
            {
                return m_ReadProcess;
            }
            set
            {
                m_ReadProcess = value;
            }
        }

        private Process m_ReadProcess = null;

        private IntPtr m_hProcess = IntPtr.Zero;

        public void OpenProcess()
        {
            //         m_hProcess = ProcessMemoryReaderApi.OpenProcess(ProcessMemoryReaderApi.PROCESS_VM_READ, 1, (uint)m_ReadProcess.Id);
            ProcessMemoryReaderApi.ProcessAccessType access;
            access = ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_READ
               | ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_WRITE
               | ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_OPERATION;
            m_hProcess = ProcessMemoryReaderApi.OpenProcess((uint)access, 1, (uint)m_ReadProcess.Id);
        }

        public void CloseHandle()
        {
            int iRetValue;
            iRetValue = ProcessMemoryReaderApi.CloseHandle(m_hProcess);
            if (iRetValue == 0)
                throw new Exception("CloseHandle failed");
        }

        public byte[] ReadProcessMemory(IntPtr MemoryAddress, uint bytesToRead, out int bytesRead)
        {
            byte[] buffer = new byte[bytesToRead];

            IntPtr ptrBytesRead;
            ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, MemoryAddress, buffer, bytesToRead, out ptrBytesRead);

            bytesRead = ptrBytesRead.ToInt32();
            //Debug.Assert(bytesRead == bytesToRead);

            return buffer;
        }

        public void WriteProcessMemory(IntPtr MemoryAddress, byte[] bytesToWrite, out int bytesWritten)
        {
            IntPtr ptrBytesWritten;
            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, MemoryAddress, bytesToWrite, (uint)bytesToWrite.Length, out ptrBytesWritten);

            bytesWritten = ptrBytesWritten.ToInt32();
        }
    }
}
Program.cs

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using ProcessMemoryReaderLib;

namespace ProcessMemoryEx
{
    class Program
    {
        static void Main(string[] args)
        {
            string processName = "";
            ProcessMemoryReaderLib.ProcessMemoryReader pReader
                               = new ProcessMemoryReaderLib.ProcessMemoryReader();

            System.Diagnostics.Process[] myProcesses
                           = System.Diagnostics.Process.GetProcessesByName(processName);

            if (myProcesses.Length == 0)
            {
                Console.WriteLine("No process found!");
                return;
            }
            pReader.ReadProcess = myProcesses[0];

            // open process in read memory mode

            pReader.OpenProcess();

            int bytesReaded;
            byte[] memory;
            // Just the start memory address to test.
            memory = pReader.ReadProcessMemory((IntPtr)0x0, 4, out bytesReaded);
            int intExample = memory[0];
            Console.WriteLine("intExample: " + intExample.ToString());

            // When trying to call this it throws an exception.
            //pReader.CloseHandle();
        }
    }
}
here is the thread that I'm getting help with, someone else may understand what they r talking about. ^^
http://social.msdn.microsoft.com/Forums ... 6b85b4dfc1

Re: C# - Reading Memory from a process

Posted: Mon Oct 20, 2008 3:21 am
by Administrator
Yeah, looks like UAC to me. You'd have to compile a manifest into your program. First step is getting a manifest file and naming it exactly like your main exe, except with a .manifest extension. Just copy micromacro.exe.manifest, and rename it to yourprogram.exe.manifest. If you place the file into the same directory as your executable, it might work just like that. Otherwise, you'll need to also compile it in as a resource file into your program.

In order to do that, you'll need to make a file, say, UacManifest.rc, and it should contain something like this:

Code: Select all

#define MANIFEST_RESOURCE_ID 1
MANIFEST_RESOURCE_ID RT_MANIFEST "res/micromacro.exe.manifest"
Where "res/micromacro.exe.manifest" needs to be changed to your manifest file's path and name. Any other specifics are compiler and language specific, so you might have to Google search a bit to find more detailed instructions.

Re: C# - Reading Memory from a process

Posted: Tue Oct 21, 2008 9:52 am
by 3cmSailorfuku
elverion wrote:Yeah, looks like UAC to me. You'd have to compile a manifest into your program. First step is getting a manifest file and naming it exactly like your main exe, except with a .manifest extension. Just copy micromacro.exe.manifest, and rename it to yourprogram.exe.manifest. If you place the file into the same directory as your executable, it might work just like that. Otherwise, you'll need to also compile it in as a resource file into your program.

In order to do that, you'll need to make a file, say, UacManifest.rc, and it should contain something like this:

Code: Select all

#define MANIFEST_RESOURCE_ID 1
MANIFEST_RESOURCE_ID RT_MANIFEST "res/micromacro.exe.manifest"
Where "res/micromacro.exe.manifest" needs to be changed to your manifest file's path and name. Any other specifics are compiler and language specific, so you might have to Google search a bit to find more detailed instructions.
C# does create the required manifest file already by default, or does it include it into the project.
Also, it does work and I get the return value correctly with no modification,
what I noticed though is that you cannot append .exe to the process name, so *.bin might not work or any other.

Re: C# - Reading Memory from a process

Posted: Tue Oct 21, 2008 12:38 pm
by Administrator
I'm not sure if you even can read from 0x0 (at least with certain "security" settings in Vista). Your best bet is to create a small sample application that declares an integer, and has a while loop with a rest in it, and nothing else. Search for the address to that integer with a memory editor, and try using that instead.

Re: C# - Reading Memory from a process

Posted: Tue Oct 21, 2008 12:56 pm
by 3cmSailorfuku
elverion wrote:I'm not sure if you even can read from 0x0 (at least with certain "security" settings in Vista). Your best bet is to create a small sample application that declares an integer, and has a while loop with a rest in it, and nothing else. Search for the address to that integer with a memory editor, and try using that instead.
Oh he does wan't to read 0x0? Because I thought it was just some placeholder or why else would anyone want to access 0x0?. Anyway, disabling UAC fixed his problem.

Re: C# - Reading Memory from a process

Posted: Tue Oct 21, 2008 4:49 pm
by Administrator
Yeah, it was just a placeholder. I thought as a subset of UAC, Vista would disallow reading from certain memory ranges, with 0x0 being within that range. I haven't heard any specific information about it, so it was just a guess.

You're right though, looks like he got it to work when disabling UAC. He must have edited that in after I read his post on MSDN.

Re: C# - Reading Memory from a process

Posted: Tue Nov 18, 2008 4:39 pm
by zer0
Apologies, when using external references, it's usually good manners, to let others know that with everyone's help I managed to solve the issue. :)